From 2f6aee1d16a89e1598760d79f18b7bf320db5f12 Mon Sep 17 00:00:00 2001 From: Andrew Sisley Date: Thu, 10 Oct 2024 10:10:02 -0400 Subject: [PATCH] WIP - Prevent mutations from secondary side of relation --- client/document.go | 34 ++++- client/errors.go | 5 + internal/db/collection.go | 25 --- internal/db/collection_update.go | 87 ----------- internal/request/graphql/schema/generate.go | 10 ++ .../one_to_many/with_alias_test.go | 29 ---- .../field_kinds/one_to_one/with_alias_test.go | 60 +------- .../one_to_one/with_null_value_test.go | 77 +--------- .../one_to_one/with_simple_test.go | 95 +----------- .../field_kinds/one_to_many/simple_test.go | 39 +---- .../one_to_many/with_alias_test.go | 61 +------- .../field_kinds/one_to_one/with_alias_test.go | 114 ++++---------- .../one_to_one/with_self_ref_test.go | 91 ----------- .../one_to_one/with_simple_test.go | 141 +++-------------- .../with_group_related_id_alias_test.go | 40 ++--- .../one_to_one/with_group_related_id_test.go | 36 ++--- .../query/one_to_one_multiple/simple_test.go | 96 ++++++------ .../query/one_to_one_to_many/simple_test.go | 28 ++-- .../query/one_to_one_to_one/simple_test.go | 100 ++++++------ .../one_to_one_to_one/with_order_test.go | 36 ++--- .../schema/create_one_one_data_test.go | 142 ++++++++++++++++++ .../updates/add/field/kind/doc_id_test.go | 8 +- tests/predefined/gen_predefined_test.go | 49 ------ 23 files changed, 430 insertions(+), 973 deletions(-) create mode 100644 tests/integration/schema/create_one_one_data_test.go diff --git a/client/document.go b/client/document.go index cc15d45673..4abadcac52 100644 --- a/client/document.go +++ b/client/document.go @@ -241,11 +241,32 @@ func validateFieldSchema(val any, field FieldDefinition) (NormalValue, error) { if err != nil { return nil, err } + + // Validate that the given value is a valid docID + _, err = NewDocIDFromString(v) + if err != nil { + return nil, err + } + return NewNormalString(v), nil } switch field.Kind { - case FieldKind_DocID, FieldKind_NILLABLE_STRING, FieldKind_NILLABLE_BLOB: + case FieldKind_DocID: + v, err := getString(val) + if err != nil { + return nil, err + } + + // Validate that the given value is a valid docID + _, err = NewDocIDFromString(v) + if err != nil { + return nil, err + } + + return NewNormalString(v), nil + + case FieldKind_NILLABLE_STRING, FieldKind_NILLABLE_BLOB: v, err := getString(val) if err != nil { return nil, err @@ -692,6 +713,17 @@ func (doc *Document) Set(field string, value any) error { if !exists { return NewErrFieldNotExist(field) } + + if fd.Kind == FieldKind_DocID && strings.HasSuffix(field, request.RelatedObjectID) { + objFieldName := strings.TrimSuffix(field, request.RelatedObjectID) + ofd, exists := doc.collectionDefinition.GetFieldByName(objFieldName) + if exists && !ofd.IsPrimaryRelation { + return NewErrCannotSetRelationFromSecondarySide(field) + } + } else if fd.Kind.IsObject() && !fd.IsPrimaryRelation { + return NewErrCannotSetRelationFromSecondarySide(field) + } + if fd.Kind.IsObject() && !fd.Kind.IsArray() { if !strings.HasSuffix(field, request.RelatedObjectID) { field = field + request.RelatedObjectID diff --git a/client/errors.go b/client/errors.go index 81ebf2e3f5..caf2fc5c10 100644 --- a/client/errors.go +++ b/client/errors.go @@ -34,6 +34,7 @@ const ( errCanNotTurnNormalValueIntoArray string = "can not turn normal value into array" errCanNotMakeNormalNilFromFieldKind string = "can not make normal nil from field kind" errFailedToParseKind string = "failed to parse kind" + errCannotSetRelationFromSecondarySide string = "cannot set relation from secondary side" ) // Errors returnable from this package. @@ -190,3 +191,7 @@ func ReviveError(message string) error { return fmt.Errorf("%s", message) } } + +func NewErrCannotSetRelationFromSecondarySide(name string) error { + return errors.New(errCannotSetRelationFromSecondarySide, errors.NewKV("Name", name)) +} diff --git a/internal/db/collection.go b/internal/db/collection.go index 8f78e51429..b746226767 100644 --- a/internal/db/collection.go +++ b/internal/db/collection.go @@ -655,31 +655,6 @@ func (c *collection) save( // that it's set to the same as the field description CRDT type. val.SetType(fieldDescription.Typ) - relationFieldDescription, isSecondaryRelationID := fieldDescription.GetSecondaryRelationField(c.Definition()) - if isSecondaryRelationID { - if val.Value() == nil { - // If the value (relation) is nil, we don't need to check for any documents already linked to it - continue - } - - primaryId := val.Value().(string) - - err = c.patchPrimaryDoc( - ctx, - c.Name().Value(), - relationFieldDescription, - primaryKey.DocID, - primaryId, - ) - if err != nil { - return cid.Undef, err - } - - // If this field was a secondary relation ID the related document will have been - // updated instead and we should discard this value - continue - } - err = c.validateOneToOneLinkDoesntAlreadyExist( ctx, doc.ID().String(), diff --git a/internal/db/collection_update.go b/internal/db/collection_update.go index 9b44f217b1..2348095500 100644 --- a/internal/db/collection_update.go +++ b/internal/db/collection_update.go @@ -13,13 +13,11 @@ package db import ( "context" - ds "github.com/ipfs/go-datastore" "github.com/sourcenetwork/immutable" "github.com/valyala/fastjson" "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/client/request" - "github.com/sourcenetwork/defradb/errors" "github.com/sourcenetwork/defradb/internal/planner" ) @@ -133,91 +131,6 @@ func (c *collection) updateWithFilter( return results, nil } -// patchPrimaryDoc patches the (primary) document linked to from the document of the given DocID via the -// given (secondary) relationship field description (hosted on the collection of the document matching the -// given DocID). -// -// The given field value should be the string representation of the DocID of the primary document to be -// patched. -func (c *collection) patchPrimaryDoc( - ctx context.Context, - secondaryCollectionName string, - relationFieldDescription client.FieldDefinition, - docID string, - fieldValue string, -) error { - primaryDocID, err := client.NewDocIDFromString(fieldValue) - if err != nil { - return err - } - - primaryDef, _, err := client.GetDefinitionFromStore(ctx, c.db, c.Definition(), relationFieldDescription.Kind) - if err != nil { - return err - } - - primaryField, ok := primaryDef.Description.GetFieldByRelation( - relationFieldDescription.RelationName, - secondaryCollectionName, - relationFieldDescription.Name, - ) - if !ok { - return client.NewErrFieldNotExist(relationFieldDescription.RelationName) - } - - primaryIDField, ok := primaryDef.GetFieldByName(primaryField.Name + request.RelatedObjectID) - if !ok { - return client.NewErrFieldNotExist(primaryField.Name + request.RelatedObjectID) - } - - primaryCol := c.db.newCollection(primaryDef.Description, primaryDef.Schema) - doc, err := primaryCol.Get( - ctx, - primaryDocID, - false, - ) - - if err != nil && !errors.Is(err, ds.ErrNotFound) { - return err - } - - // If the document doesn't exist then there is nothing to update. - if doc == nil { - return nil - } - - err = primaryCol.validateOneToOneLinkDoesntAlreadyExist( - ctx, - primaryDocID.String(), - primaryIDField, - docID, - ) - if err != nil { - return err - } - - existingVal, err := doc.GetValue(primaryIDField.Name) - if err != nil && !errors.Is(err, client.ErrFieldNotExist) { - return err - } - - if existingVal != nil && existingVal.Value() != "" && existingVal.Value() != docID { - return NewErrOneOneAlreadyLinked(docID, fieldValue, relationFieldDescription.RelationName) - } - - err = doc.Set(primaryIDField.Name, docID) - if err != nil { - return err - } - - err = primaryCol.Update(ctx, doc) - if err != nil { - return err - } - - return nil -} - // makeSelectionPlan constructs a simple read-only plan of the collection using the given filter. // currently it doesn't support any other operations other than filters. // (IE: No limit, order, etc) diff --git a/internal/request/graphql/schema/generate.go b/internal/request/graphql/schema/generate.go index f326a8232a..2b7ce94d2c 100644 --- a/internal/request/graphql/schema/generate.go +++ b/internal/request/graphql/schema/generate.go @@ -566,6 +566,16 @@ func (g *Generator) buildMutationInputTypes(collections []client.CollectionDefin continue } + if field.Kind == client.FieldKind_DocID && strings.HasSuffix(field.Name, request.RelatedObjectID) { + objFieldName := strings.TrimSuffix(field.Name, request.RelatedObjectID) + ofd, exists := collection.GetFieldByName(objFieldName) + if exists && !ofd.IsPrimaryRelation { + continue + } + } else if field.Kind.IsObject() && !field.IsPrimaryRelation { + continue + } + var ttype gql.Type if field.Kind.IsObject() { if field.Kind.IsArray() { diff --git a/tests/integration/mutation/create/field_kinds/one_to_many/with_alias_test.go b/tests/integration/mutation/create/field_kinds/one_to_many/with_alias_test.go index fe66f58d98..7b43fe8499 100644 --- a/tests/integration/mutation/create/field_kinds/one_to_many/with_alias_test.go +++ b/tests/integration/mutation/create/field_kinds/one_to_many/with_alias_test.go @@ -94,35 +94,6 @@ func TestMutationCreateOneToMany_AliasedRelationNameNonExistingRelationManySide_ } executeTestCase(t, test) } -func TestMutationCreateOneToMany_AliasedRelationNameInvalidIDManySide_CreatedDoc(t *testing.T) { - test := testUtils.TestCase{ - Description: "One to many create mutation, invalid id, from the many side, with alias", - Actions: []any{ - testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Painted House", - "author": "ValueDoesntMatter" - }`, - }, - testUtils.Request{ - Request: `query { - Book { - name - } - }`, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - }, - }, - }, - }, - }, - } - executeTestCase(t, test) -} func TestMutationCreateOneToMany_AliasedRelationNameToLinkFromManySide(t *testing.T) { test := testUtils.TestCase{ diff --git a/tests/integration/mutation/create/field_kinds/one_to_one/with_alias_test.go b/tests/integration/mutation/create/field_kinds/one_to_one/with_alias_test.go index 8c7dddb1c2..999c6d3de3 100644 --- a/tests/integration/mutation/create/field_kinds/one_to_one/with_alias_test.go +++ b/tests/integration/mutation/create/field_kinds/one_to_one/with_alias_test.go @@ -73,23 +73,6 @@ func TestMutationCreateOneToOne_UseAliasWithNonExistingRelationPrimarySide_Creat executeTestCase(t, test) } -func TestMutationCreateOneToOne_UseAliasWithNonExistingRelationSecondarySide_Error(t *testing.T) { - test := testUtils.TestCase{ - Description: "One to one create mutation, alias relation, from the secondary side", - Actions: []any{ - testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Painted House", - "author": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" - }`, - ExpectedError: "document not found or not authorized to access", - }, - }, - } - executeTestCase(t, test) -} - func TestMutationCreateOneToOne_UseAliasedRelationNameToLink_QueryFromPrimarySide(t *testing.T) { test := testUtils.TestCase{ Description: "One to one create mutation with an alias relation.", @@ -153,7 +136,7 @@ func TestMutationCreateOneToOne_UseAliasedRelationNameToLink_QueryFromPrimarySid executeTestCase(t, test) } -func TestMutationCreateOneToOne_UseAliasedRelationNameToLink_QueryFromSecondarySide(t *testing.T) { +func TestMutationCreateOneToOne_UseAliasedRelationNameToLink_Errors(t *testing.T) { test := testUtils.TestCase{ Description: "One to one create mutation from secondary side with alias relation.", Actions: []any{ @@ -169,46 +152,7 @@ func TestMutationCreateOneToOne_UseAliasedRelationNameToLink_QueryFromSecondaryS "name": "Painted House", "author": testUtils.NewDocIndex(1, 0), }, - }, - testUtils.Request{ - Request: `query { - Author { - name - published { - name - } - } - }`, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "published": map[string]any{ - "name": "Painted House", - }, - }, - }, - }, - }, - testUtils.Request{ - Request: `query { - Book { - name - author { - name - } - } - }`, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "author": map[string]any{ - "name": "John Grisham", - }, - }, - }, - }, + ExpectedError: "cannot set relation from secondary side", }, }, } diff --git a/tests/integration/mutation/create/field_kinds/one_to_one/with_null_value_test.go b/tests/integration/mutation/create/field_kinds/one_to_one/with_null_value_test.go index a6421aec5c..d82b515dc7 100644 --- a/tests/integration/mutation/create/field_kinds/one_to_one/with_null_value_test.go +++ b/tests/integration/mutation/create/field_kinds/one_to_one/with_null_value_test.go @@ -32,77 +32,17 @@ func TestMutationCreateOneToOne_WithExplicitNullOnPrimarySide(t *testing.T) { } `, }, - testUtils.CreateDoc{ - Doc: `{ - "name": "How to Be a Canadian", - "author": null - }`, - }, - testUtils.CreateDoc{ - Doc: `{ - "name": "Secrets at Maple Syrup Farm", - "author": null - }`, - }, testUtils.CreateDoc{ CollectionID: 1, DocMap: map[string]any{ - "name": "Will Ferguson", - "published": testUtils.NewDocIndex(0, 0), + "name": "Will Ferguson", }, }, - testUtils.Request{ - Request: ` - query { - Book { - name - author { - name - } - } - }`, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Secrets at Maple Syrup Farm", - "author": nil, - }, - { - "name": "How to Be a Canadian", - "author": map[string]any{ - "name": "Will Ferguson", - }, - }, - }, - }, - }, - }, - } - - testUtils.ExecuteTestCase(t, test) -} - -func TestMutationCreateOneToOne_WithExplicitNullOnSecondarySide(t *testing.T) { - test := testUtils.TestCase{ - Actions: []any{ - testUtils.SchemaUpdate{ - Schema: ` - type Book { - name: String - author: Author - } - - type Author { - name: String - published: Book @primary - } - `, - }, testUtils.CreateDoc{ - Doc: `{ - "name": "How to Be a Canadian", - "author": null - }`, + DocMap: map[string]any{ + "name": "How to Be a Canadian", + "author": testUtils.NewDocIndex(1, 0), + }, }, testUtils.CreateDoc{ Doc: `{ @@ -110,13 +50,6 @@ func TestMutationCreateOneToOne_WithExplicitNullOnSecondarySide(t *testing.T) { "author": null }`, }, - testUtils.CreateDoc{ - CollectionID: 1, - DocMap: map[string]any{ - "name": "Will Ferguson", - "published": testUtils.NewDocIndex(0, 0), - }, - }, testUtils.Request{ Request: ` query { diff --git a/tests/integration/mutation/create/field_kinds/one_to_one/with_simple_test.go b/tests/integration/mutation/create/field_kinds/one_to_one/with_simple_test.go index fabced3505..c366e4f459 100644 --- a/tests/integration/mutation/create/field_kinds/one_to_one/with_simple_test.go +++ b/tests/integration/mutation/create/field_kinds/one_to_one/with_simple_test.go @@ -73,23 +73,6 @@ func TestMutationCreateOneToOneNoChild(t *testing.T) { executeTestCase(t, test) } -func TestMutationCreateOneToOne_NonExistingRelationSecondarySide_Error(t *testing.T) { - test := testUtils.TestCase{ - Description: "One to one create mutation, from the secondary side", - Actions: []any{ - testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Painted House", - "author_id": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" - }`, - ExpectedError: "document not found or not authorized to access", - }, - }, - } - executeTestCase(t, test) -} - func TestMutationCreateOneToOne(t *testing.T) { test := testUtils.TestCase{ Description: "One to one create mutation", @@ -168,51 +151,10 @@ func TestMutationCreateOneToOneSecondarySide(t *testing.T) { testUtils.CreateDoc{ CollectionID: 0, DocMap: map[string]any{ - "name": "Painted House", - "author_id": testUtils.NewDocIndex(1, 0), - }, - }, - testUtils.Request{ - Request: ` - query { - Author { - name - published { - name - } - } - }`, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "published": map[string]any{ - "name": "Painted House", - }, - }, - }, - }, - }, - testUtils.Request{ - Request: ` - query { - Book { - name - author { - name - } - } - }`, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "author": map[string]any{ - "name": "John Grisham", - }, - }, - }, + "name": "Painted House", + "author": testUtils.NewDocIndex(1, 0), }, + ExpectedError: "cannot set relation from secondary side", }, }, } @@ -250,34 +192,3 @@ func TestMutationCreateOneToOne_ErrorsGivenRelationAlreadyEstablishedViaPrimary( executeTestCase(t, test) } - -func TestMutationCreateOneToOne_ErrorsGivenRelationAlreadyEstablishedViaSecondary(t *testing.T) { - test := testUtils.TestCase{ - Description: "One to one create mutation, errors due to link already existing, secondary side", - Actions: []any{ - testUtils.CreateDoc{ - CollectionID: 1, - Doc: `{ - "name": "John Grisham" - }`, - }, - testUtils.CreateDoc{ - CollectionID: 0, - DocMap: map[string]any{ - "name": "Painted House", - "author_id": testUtils.NewDocIndex(1, 0), - }, - }, - testUtils.CreateDoc{ - CollectionID: 0, - DocMap: map[string]any{ - "name": "Golestan", - "author_id": testUtils.NewDocIndex(1, 0), - }, - ExpectedError: "target document is already linked to another document.", - }, - }, - } - - executeTestCase(t, test) -} diff --git a/tests/integration/mutation/update/field_kinds/one_to_many/simple_test.go b/tests/integration/mutation/update/field_kinds/one_to_many/simple_test.go index e8ac15e4da..7c6d33af56 100644 --- a/tests/integration/mutation/update/field_kinds/one_to_many/simple_test.go +++ b/tests/integration/mutation/update/field_kinds/one_to_many/simple_test.go @@ -72,8 +72,6 @@ func TestMutationUpdateOneToMany_RelationIDToLinkFromSingleSide_Error(t *testing executeTestCase(t, test) } -// Note: This test should probably not pass, as it contains a -// reference to a document that doesnt exist. func TestMutationUpdateOneToMany_InvalidRelationIDToLinkFromManySide(t *testing.T) { author1ID := "bae-a47f80ab-1c30-53b3-9dac-04a4a3fda77e" invalidAuthorID := "bae-35953ca-518d-9e6b-9ce6cd00eff5" @@ -106,42 +104,7 @@ func TestMutationUpdateOneToMany_InvalidRelationIDToLinkFromManySide(t *testing. }`, invalidAuthorID, ), - }, - testUtils.Request{ - Request: `query { - Author { - name - published { - name - } - } - }`, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "published": []map[string]any{}, - }, - }, - }, - }, - testUtils.Request{ - Request: `query { - Book { - name - author { - name - } - } - }`, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "author": nil, // Linked to incorrect id - }, - }, - }, + ExpectedError: "uuid: incorrect UUID length 30 in string", }, }, } diff --git a/tests/integration/mutation/update/field_kinds/one_to_many/with_alias_test.go b/tests/integration/mutation/update/field_kinds/one_to_many/with_alias_test.go index 1f0375e6ba..bd68e707ca 100644 --- a/tests/integration/mutation/update/field_kinds/one_to_many/with_alias_test.go +++ b/tests/integration/mutation/update/field_kinds/one_to_many/with_alias_test.go @@ -51,14 +51,13 @@ func TestMutationUpdateOneToMany_AliasRelationNameToLinkFromSingleSide_Collectio testUtils.UpdateDoc{ CollectionID: 1, DocID: 1, - // NOTE: There is no `published` on book. Doc: fmt.Sprintf( `{ "published": "%s" }`, bookID, ), - ExpectedError: "The given field does not exist. Name: published", + ExpectedError: "cannot set relation from secondary side", }, }, } @@ -100,42 +99,7 @@ func TestMutationUpdateOneToMany_InvalidAliasRelationNameToLinkFromManySide_GQL( }`, invalidAuthorID, ), - }, - testUtils.Request{ - Request: `query { - Author { - name - published { - name - } - } - }`, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "published": []map[string]any{}, - }, - }, - }, - }, - testUtils.Request{ - Request: `query { - Book { - name - author { - name - } - } - }`, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "author": nil, // Linked to incorrect id - }, - }, - }, + ExpectedError: "uuid: incorrect UUID length 30 in string", }, }, } @@ -143,8 +107,6 @@ func TestMutationUpdateOneToMany_InvalidAliasRelationNameToLinkFromManySide_GQL( executeTestCase(t, test) } -// Note: This test should probably not pass, as it contains a -// reference to a document that doesnt exist. func TestMutationUpdateOneToMany_InvalidAliasRelationNameToLinkFromManySide_Collection(t *testing.T) { author1ID := "bae-a47f80ab-1c30-53b3-9dac-04a4a3fda77e" invalidAuthorID := "bae-35953ca-518d-9e6b-9ce6cd00eff5" @@ -177,24 +139,7 @@ func TestMutationUpdateOneToMany_InvalidAliasRelationNameToLinkFromManySide_Coll }`, invalidAuthorID, ), - }, - testUtils.Request{ - Request: `query { - Book { - name - author { - name - } - } - }`, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "author": nil, - }, - }, - }, + ExpectedError: "uuid: incorrect UUID length 30 in string", }, }, } diff --git a/tests/integration/mutation/update/field_kinds/one_to_one/with_alias_test.go b/tests/integration/mutation/update/field_kinds/one_to_one/with_alias_test.go index eda176bbcc..768aa77e45 100644 --- a/tests/integration/mutation/update/field_kinds/one_to_one/with_alias_test.go +++ b/tests/integration/mutation/update/field_kinds/one_to_one/with_alias_test.go @@ -20,34 +20,30 @@ import ( ) func TestMutationUpdateOneToOne_AliasRelationNameToLinkFromPrimarySide(t *testing.T) { - author1ID := "bae-53eff350-ad8e-532c-b72d-f95c4f47909c" - bookID := "bae-89d64ba1-44e3-5d75-a610-7226077ece48" + bookID := "bae-dafb74e9-2bf1-5f12-aea9-967814592bad" test := testUtils.TestCase{ Description: "One to one update mutation using alias relation id from single side", Actions: []any{ testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, Doc: `{ - "name": "John Grisham" + "name": "Painted House" }`, }, + testUtils.CreateDoc{ + CollectionID: 1, + DocMap: map[string]any{ + "name": "John Grisham", + "published": testUtils.NewDocIndex(0, 0), + }, + }, testUtils.CreateDoc{ CollectionID: 1, Doc: `{ "name": "New Shahzad" }`, }, - testUtils.CreateDoc{ - CollectionID: 0, - Doc: fmt.Sprintf( - `{ - "name": "Painted House", - "author": "%s" - }`, - author1ID, - ), - }, testUtils.UpdateDoc{ CollectionID: 1, DocID: 1, @@ -66,34 +62,30 @@ func TestMutationUpdateOneToOne_AliasRelationNameToLinkFromPrimarySide(t *testin } func TestMutationUpdateOneToOne_AliasRelationNameToLinkFromSecondarySide(t *testing.T) { - author1ID := "bae-53eff350-ad8e-532c-b72d-f95c4f47909c" author2ID := "bae-c058cfd4-259f-5b08-975d-106f13a143d5" test := testUtils.TestCase{ Description: "One to one update mutation using alias relation id from secondary side", Actions: []any{ testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, Doc: `{ - "name": "John Grisham" + "name": "Painted House" }`, }, + testUtils.CreateDoc{ + CollectionID: 1, + DocMap: map[string]any{ + "name": "John Grisham", + "published": testUtils.NewDocIndex(0, 0), + }, + }, testUtils.CreateDoc{ CollectionID: 1, Doc: `{ "name": "New Shahzad" }`, }, - testUtils.CreateDoc{ - CollectionID: 0, - Doc: fmt.Sprintf( - `{ - "name": "Painted House", - "author": "%s" - }`, - author1ID, - ), - }, testUtils.UpdateDoc{ CollectionID: 0, DocID: 0, @@ -103,7 +95,7 @@ func TestMutationUpdateOneToOne_AliasRelationNameToLinkFromSecondarySide(t *test }`, author2ID, ), - ExpectedError: "target document is already linked to another document.", + ExpectedError: "cannot set relation from secondary side", }, }, } @@ -112,79 +104,35 @@ func TestMutationUpdateOneToOne_AliasRelationNameToLinkFromSecondarySide(t *test } func TestMutationUpdateOneToOne_AliasWithInvalidLengthRelationIDToLink_Error(t *testing.T) { - author1ID := "bae-53eff350-ad8e-532c-b72d-f95c4f47909c" invalidLenSubID := "35953ca-518d-9e6b-9ce6cd00eff5" - invalidAuthorID := "bae-" + invalidLenSubID + invalidBookID := "bae-" + invalidLenSubID test := testUtils.TestCase{ Description: "One to one update mutation using invalid alias relation id", Actions: []any{ testUtils.CreateDoc{ - CollectionID: 1, - Doc: `{ - "name": "John Grisham" - }`, - }, - testUtils.CreateDoc{ - CollectionID: 0, - Doc: fmt.Sprintf( - `{ - "name": "Painted House", - "author": "%s" - }`, - author1ID, - ), - }, - testUtils.UpdateDoc{ CollectionID: 0, - DocID: 0, - Doc: fmt.Sprintf( - `{ - "author": "%s" - }`, - invalidAuthorID, - ), - ExpectedError: "uuid: incorrect UUID length 30 in string \"" + invalidLenSubID + "\"", - }, - }, - } - - executeTestCase(t, test) -} - -func TestMutationUpdateOneToOne_InvalidAliasRelationNameToLinkFromSecondarySide_Error(t *testing.T) { - author1ID := "bae-53eff350-ad8e-532c-b72d-f95c4f47909c" - invalidAuthorID := "bae-2edb7fdd-cad7-5ad4-9c7d-6920245a96ee" - - test := testUtils.TestCase{ - Description: "One to one update mutation using alias relation id from secondary side", - Actions: []any{ - testUtils.CreateDoc{ - CollectionID: 1, Doc: `{ - "name": "John Grisham" + "name": "Painted House" }`, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: fmt.Sprintf( - `{ - "name": "Painted House", - "author": "%s" - }`, - author1ID, - ), + CollectionID: 1, + DocMap: map[string]any{ + "name": "John Grisham", + "published": testUtils.NewDocIndex(0, 0), + }, }, testUtils.UpdateDoc{ - CollectionID: 0, + CollectionID: 1, DocID: 0, Doc: fmt.Sprintf( `{ - "author": "%s" + "published": "%s" }`, - invalidAuthorID, + invalidBookID, ), - ExpectedError: "document not found or not authorized to access", + ExpectedError: "uuid: incorrect UUID length 30 in string \"" + invalidLenSubID + "\"", }, }, } diff --git a/tests/integration/mutation/update/field_kinds/one_to_one/with_self_ref_test.go b/tests/integration/mutation/update/field_kinds/one_to_one/with_self_ref_test.go index dd630c0721..77087f2186 100644 --- a/tests/integration/mutation/update/field_kinds/one_to_one/with_self_ref_test.go +++ b/tests/integration/mutation/update/field_kinds/one_to_one/with_self_ref_test.go @@ -106,94 +106,3 @@ func TestMutationUpdateOneToOne_SelfReferencingFromPrimary(t *testing.T) { testUtils.ExecuteTestCase(t, test) } - -func TestMutationUpdateOneToOne_SelfReferencingFromSecondary(t *testing.T) { - user1ID := "bae-a86ab69e-a2be-54b9-b66e-4e30d6778ffe" - - test := testUtils.TestCase{ - Description: "One to one update mutation, self referencing from secondary", - - Actions: []any{ - testUtils.SchemaUpdate{ - Schema: ` - type User { - name: String - boss: User - underling: User @primary - } - `, - }, - testUtils.CreateDoc{ - Doc: `{ - "name": "John" - }`, - }, - testUtils.CreateDoc{ - Doc: `{ - "name": "Fred" - }`, - }, - testUtils.UpdateDoc{ - DocID: 1, - Doc: fmt.Sprintf( - `{ - "boss_id": "%s" - }`, - user1ID, - ), - }, - testUtils.Request{ - Request: ` - query { - User { - name - boss { - name - } - } - }`, - Results: map[string]any{ - "User": []map[string]any{ - { - "name": "Fred", - "boss": map[string]any{ - "name": "John", - }, - }, - { - "name": "John", - "boss": nil, - }, - }, - }, - }, - testUtils.Request{ - Request: ` - query { - User { - name - underling { - name - } - } - }`, - Results: map[string]any{ - "User": []map[string]any{ - { - "name": "Fred", - "underling": nil, - }, - { - "name": "John", - "underling": map[string]any{ - "name": "Fred", - }, - }, - }, - }, - }, - }, - } - - testUtils.ExecuteTestCase(t, test) -} diff --git a/tests/integration/mutation/update/field_kinds/one_to_one/with_simple_test.go b/tests/integration/mutation/update/field_kinds/one_to_one/with_simple_test.go index b2b3859d2d..8d06bae2fd 100644 --- a/tests/integration/mutation/update/field_kinds/one_to_one/with_simple_test.go +++ b/tests/integration/mutation/update/field_kinds/one_to_one/with_simple_test.go @@ -161,52 +161,11 @@ func TestMutationUpdateOneToOneSecondarySide(t *testing.T) { DocID: 0, Doc: fmt.Sprintf( `{ - "author_id": "%s" + "author": "%s" }`, authorID, ), - }, - testUtils.Request{ - Request: ` - query { - Book { - name - author { - name - } - } - }`, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "author": map[string]any{ - "name": "John Grisham", - }, - }, - }, - }, - }, - testUtils.Request{ - Request: ` - query { - Author { - name - published { - name - } - } - }`, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "published": map[string]any{ - "name": "Painted House", - }, - }, - }, - }, + ExpectedError: "cannot set relation from secondary side", }, }, } @@ -214,34 +173,30 @@ func TestMutationUpdateOneToOneSecondarySide(t *testing.T) { } func TestMutationUpdateOneToOne_RelationIDToLinkFromPrimarySide(t *testing.T) { - author1ID := "bae-53eff350-ad8e-532c-b72d-f95c4f47909c" - bookID := "bae-89d64ba1-44e3-5d75-a610-7226077ece48" + bookID := "bae-dafb74e9-2bf1-5f12-aea9-967814592bad" test := testUtils.TestCase{ Description: "One to one update mutation using relation id from single side (wrong)", Actions: []any{ testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, Doc: `{ - "name": "John Grisham" + "name": "Painted House" }`, }, + testUtils.CreateDoc{ + CollectionID: 1, + DocMap: map[string]any{ + "name": "John Grisham", + "published_id": testUtils.NewDocIndex(0, 0), + }, + }, testUtils.CreateDoc{ CollectionID: 1, Doc: `{ "name": "New Shahzad" }`, }, - testUtils.CreateDoc{ - CollectionID: 0, - Doc: fmt.Sprintf( - `{ - "name": "Painted House", - "author_id": "%s" - }`, - author1ID, - ), - }, testUtils.UpdateDoc{ CollectionID: 1, DocID: 1, @@ -260,7 +215,6 @@ func TestMutationUpdateOneToOne_RelationIDToLinkFromPrimarySide(t *testing.T) { } func TestMutationUpdateOneToOne_RelationIDToLinkFromSecondarySide(t *testing.T) { - author1ID := "bae-53eff350-ad8e-532c-b72d-f95c4f47909c" author2ID := "bae-c058cfd4-259f-5b08-975d-106f13a143d5" test := testUtils.TestCase{ @@ -280,13 +234,9 @@ func TestMutationUpdateOneToOne_RelationIDToLinkFromSecondarySide(t *testing.T) }, testUtils.CreateDoc{ CollectionID: 0, - Doc: fmt.Sprintf( - `{ - "name": "Painted House", - "author_id": "%s" - }`, - author1ID, - ), + Doc: `{ + "name": "Painted House" + }`, }, testUtils.UpdateDoc{ CollectionID: 0, @@ -297,7 +247,7 @@ func TestMutationUpdateOneToOne_RelationIDToLinkFromSecondarySide(t *testing.T) }`, author2ID, ), - ExpectedError: "target document is already linked to another document.", + ExpectedError: "cannot set relation from secondary side", }, }, } @@ -306,79 +256,34 @@ func TestMutationUpdateOneToOne_RelationIDToLinkFromSecondarySide(t *testing.T) } func TestMutationUpdateOneToOne_InvalidLengthRelationIDToLink_Error(t *testing.T) { - author1ID := "bae-53eff350-ad8e-532c-b72d-f95c4f47909c" invalidLenSubID := "35953ca-518d-9e6b-9ce6cd00eff5" - invalidAuthorID := "bae-" + invalidLenSubID + invalidBookID := "bae-" + invalidLenSubID test := testUtils.TestCase{ Description: "One to one update mutation using invalid relation id", Actions: []any{ testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, Doc: `{ - "name": "John Grisham" + "name": "Painted House" }`, }, - testUtils.CreateDoc{ - CollectionID: 0, - Doc: fmt.Sprintf( - `{ - "name": "Painted House", - "author_id": "%s" - }`, - author1ID, - ), - }, - testUtils.UpdateDoc{ - CollectionID: 0, - DocID: 0, - Doc: fmt.Sprintf( - `{ - "author_id": "%s" - }`, - invalidAuthorID, - ), - ExpectedError: "uuid: incorrect UUID length 30 in string \"" + invalidLenSubID + "\"", - }, - }, - } - - executeTestCase(t, test) -} - -func TestMutationUpdateOneToOne_InvalidRelationIDToLinkFromSecondarySide_Error(t *testing.T) { - author1ID := "bae-53eff350-ad8e-532c-b72d-f95c4f47909c" - invalidAuthorID := "bae-2edb7fdd-cad7-5ad4-9c7d-6920245a96ee" - - test := testUtils.TestCase{ - Description: "One to one update mutation using relation id from secondary side", - Actions: []any{ testUtils.CreateDoc{ CollectionID: 1, Doc: `{ "name": "John Grisham" }`, }, - testUtils.CreateDoc{ - CollectionID: 0, - Doc: fmt.Sprintf( - `{ - "name": "Painted House", - "author_id": "%s" - }`, - author1ID, - ), - }, testUtils.UpdateDoc{ - CollectionID: 0, + CollectionID: 1, DocID: 0, Doc: fmt.Sprintf( `{ - "author_id": "%s" + "published_id": "%s" }`, - invalidAuthorID, + invalidBookID, ), - ExpectedError: "document not found or not authorized to access", + ExpectedError: "uuid: incorrect UUID length 30 in string \"" + invalidLenSubID + "\"", }, }, } diff --git a/tests/integration/query/one_to_one/with_group_related_id_alias_test.go b/tests/integration/query/one_to_one/with_group_related_id_alias_test.go index 0ae9548536..4581914473 100644 --- a/tests/integration/query/one_to_one/with_group_related_id_alias_test.go +++ b/tests/integration/query/one_to_one/with_group_related_id_alias_test.go @@ -34,29 +34,29 @@ func TestQueryOneToOneWithGroupRelatedIDAlias(t *testing.T) { `, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Painted House" - }`, + CollectionID: 1, + DocMap: map[string]any{ + "name": "John Grisham", + }, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Go Guide for Rust developers" - }`, + CollectionID: 1, + DocMap: map[string]any{ + "name": "Andrew Lone", + }, }, testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, DocMap: map[string]any{ - "name": "John Grisham", - "published_id": testUtils.NewDocIndex(0, 0), + "name": "Painted House", + "author_id": testUtils.NewDocIndex(1, 0), }, }, testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, DocMap: map[string]any{ - "name": "Andrew Lone", - "published_id": testUtils.NewDocIndex(0, 1), + "name": "Go Guide for Rust developers", + "author_id": testUtils.NewDocIndex(1, 1), }, }, testUtils.Request{ @@ -74,24 +74,24 @@ func TestQueryOneToOneWithGroupRelatedIDAlias(t *testing.T) { Results: map[string]any{ "Book": []map[string]any{ { - "author_id": "bae-fc7bf08d-9117-5acd-8b49-bc7431b1b238", + "author_id": "bae-547eb3d8-7fc8-5c21-bcef-590813451e55", "author": map[string]any{ - "name": "John Grisham", + "name": "Andrew Lone", }, "_group": []map[string]any{ { - "name": "Painted House", + "name": "Go Guide for Rust developers", }, }, }, { - "author_id": "bae-fcb12812-4c38-574e-bc8b-91b37ee6cd9b", + "author_id": "bae-ee5973cf-73c3-558f-8aec-8b590b8e77cf", "author": map[string]any{ - "name": "Andrew Lone", + "name": "John Grisham", }, "_group": []map[string]any{ { - "name": "Go Guide for Rust developers", + "name": "Painted House", }, }, }, diff --git a/tests/integration/query/one_to_one/with_group_related_id_test.go b/tests/integration/query/one_to_one/with_group_related_id_test.go index 5b1aa09dce..aa3c0e9c17 100644 --- a/tests/integration/query/one_to_one/with_group_related_id_test.go +++ b/tests/integration/query/one_to_one/with_group_related_id_test.go @@ -34,29 +34,29 @@ func TestQueryOneToOneWithGroupRelatedID(t *testing.T) { `, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Painted House" - }`, + CollectionID: 1, + DocMap: map[string]any{ + "name": "John Grisham", + }, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Go Guide for Rust developers" - }`, + CollectionID: 1, + DocMap: map[string]any{ + "name": "Andrew Lone", + }, }, testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, DocMap: map[string]any{ - "name": "John Grisham", - "published_id": testUtils.NewDocIndex(0, 0), + "name": "Painted House", + "author_id": testUtils.NewDocIndex(1, 0), }, }, testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, DocMap: map[string]any{ - "name": "John Grisham", - "published_id": testUtils.NewDocIndex(0, 1), + "name": "Go Guide for Rust developers", + "author_id": testUtils.NewDocIndex(1, 1), }, }, testUtils.Request{ @@ -71,18 +71,18 @@ func TestQueryOneToOneWithGroupRelatedID(t *testing.T) { Results: map[string]any{ "Book": []map[string]any{ { - "author_id": "bae-fc7bf08d-9117-5acd-8b49-bc7431b1b238", + "author_id": "bae-547eb3d8-7fc8-5c21-bcef-590813451e55", "_group": []map[string]any{ { - "name": "Painted House", + "name": "Go Guide for Rust developers", }, }, }, { - "author_id": "bae-f2dcf043-d24d-5885-9a0a-60196094c782", + "author_id": "bae-ee5973cf-73c3-558f-8aec-8b590b8e77cf", "_group": []map[string]any{ { - "name": "Go Guide for Rust developers", + "name": "Painted House", }, }, }, diff --git a/tests/integration/query/one_to_one_multiple/simple_test.go b/tests/integration/query/one_to_one_multiple/simple_test.go index 4696db5dcf..5ab21e7543 100644 --- a/tests/integration/query/one_to_one_multiple/simple_test.go +++ b/tests/integration/query/one_to_one_multiple/simple_test.go @@ -143,18 +143,6 @@ func TestQueryOneToOneMultiple_FromMixedPrimaryAndSecondary(t *testing.T) { } `, }, - testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Old Publisher" - }`, - }, - testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "New Publisher" - }`, - }, testUtils.CreateDoc{ CollectionID: 1, Doc: `{ @@ -170,17 +158,29 @@ func TestQueryOneToOneMultiple_FromMixedPrimaryAndSecondary(t *testing.T) { testUtils.CreateDoc{ CollectionID: 2, DocMap: map[string]any{ - "name": "Painted House", - "publisher_id": testUtils.NewDocIndex(0, 0), - "author_id": testUtils.NewDocIndex(1, 0), + "name": "Painted House", + "author_id": testUtils.NewDocIndex(1, 0), }, }, testUtils.CreateDoc{ CollectionID: 2, DocMap: map[string]any{ - "name": "Theif Lord", - "publisher_id": testUtils.NewDocIndex(0, 1), - "author_id": testUtils.NewDocIndex(1, 1), + "name": "Theif Lord", + "author_id": testUtils.NewDocIndex(1, 1), + }, + }, + testUtils.CreateDoc{ + CollectionID: 0, + DocMap: map[string]any{ + "name": "Old Publisher", + "printed_id": testUtils.NewDocIndex(2, 0), + }, + }, + testUtils.CreateDoc{ + CollectionID: 0, + DocMap: map[string]any{ + "name": "New Publisher", + "printed_id": testUtils.NewDocIndex(2, 1), }, }, testUtils.Request{ @@ -248,43 +248,43 @@ func TestQueryOneToOneMultiple_FromSecondary(t *testing.T) { `, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Old Publisher" - }`, + CollectionID: 2, + DocMap: map[string]any{ + "name": "Painted House", + }, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "New Publisher" - }`, + CollectionID: 2, + DocMap: map[string]any{ + "name": "Theif Lord", + }, }, testUtils.CreateDoc{ - CollectionID: 1, - Doc: `{ - "name": "John Grisham" - }`, + CollectionID: 0, + DocMap: map[string]any{ + "name": "Old Publisher", + "printed_id": testUtils.NewDocIndex(2, 0), + }, }, testUtils.CreateDoc{ - CollectionID: 1, - Doc: `{ - "name": "Cornelia Funke" - }`, + CollectionID: 0, + DocMap: map[string]any{ + "name": "New Publisher", + "printed_id": testUtils.NewDocIndex(2, 1), + }, }, testUtils.CreateDoc{ - CollectionID: 2, + CollectionID: 1, DocMap: map[string]any{ - "name": "Painted House", - "publisher_id": testUtils.NewDocIndex(0, 0), - "author_id": testUtils.NewDocIndex(1, 0), + "name": "John Grisham", + "published_id": testUtils.NewDocIndex(2, 0), }, }, testUtils.CreateDoc{ - CollectionID: 2, + CollectionID: 1, DocMap: map[string]any{ - "name": "Theif Lord", - "publisher_id": testUtils.NewDocIndex(0, 1), - "author_id": testUtils.NewDocIndex(1, 1), + "name": "Cornelia Funke", + "published_id": testUtils.NewDocIndex(2, 1), }, }, testUtils.Request{ @@ -302,21 +302,21 @@ func TestQueryOneToOneMultiple_FromSecondary(t *testing.T) { Results: map[string]any{ "Book": []map[string]any{ { - "name": "Theif Lord", + "name": "Painted House", "publisher": map[string]any{ - "name": "New Publisher", + "name": "Old Publisher", }, "author": map[string]any{ - "name": "Cornelia Funke", + "name": "John Grisham", }, }, { - "name": "Painted House", + "name": "Theif Lord", "publisher": map[string]any{ - "name": "Old Publisher", + "name": "New Publisher", }, "author": map[string]any{ - "name": "John Grisham", + "name": "Cornelia Funke", }, }, }, diff --git a/tests/integration/query/one_to_one_to_many/simple_test.go b/tests/integration/query/one_to_one_to_many/simple_test.go index 3e65193cc7..e360d7a698 100644 --- a/tests/integration/query/one_to_one_to_many/simple_test.go +++ b/tests/integration/query/one_to_one_to_many/simple_test.go @@ -115,16 +115,16 @@ func TestQueryOneToOneToManyFromSecondaryOnOneToMany(t *testing.T) { `, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Indicator1" - }`, + CollectionID: 1, + DocMap: map[string]any{ + "name": "Observable1", + }, }, testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, DocMap: map[string]any{ - "name": "Observable1", - "indicator_id": testUtils.NewDocIndex(0, 0), + "name": "Indicator1", + "observable_id": testUtils.NewDocIndex(1, 0), }, }, testUtils.CreateDoc{ @@ -192,16 +192,16 @@ func TestQueryOneToOneToManyFromSecondaryOnOneToOne(t *testing.T) { `, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Indicator1" - }`, + CollectionID: 1, + DocMap: map[string]any{ + "name": "Observable1", + }, }, testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, DocMap: map[string]any{ - "name": "Observable1", - "indicator_id": testUtils.NewDocIndex(0, 0), + "name": "Indicator1", + "observable_id": testUtils.NewDocIndex(1, 0), }, }, testUtils.CreateDoc{ diff --git a/tests/integration/query/one_to_one_to_one/simple_test.go b/tests/integration/query/one_to_one_to_one/simple_test.go index 0486d3db77..e338d0f47e 100644 --- a/tests/integration/query/one_to_one_to_one/simple_test.go +++ b/tests/integration/query/one_to_one_to_one/simple_test.go @@ -40,43 +40,43 @@ func TestQueryOneToOneToOne(t *testing.T) { `, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Old Publisher" - }`, + CollectionID: 2, + DocMap: map[string]any{ + "name": "John Grisham", + }, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "New Publisher" - }`, + CollectionID: 2, + DocMap: map[string]any{ + "name": "Cornelia Funke", + }, }, testUtils.CreateDoc{ CollectionID: 1, DocMap: map[string]any{ - "name": "Painted House", - "publisher_id": testUtils.NewDocIndex(0, 0), + "name": "Painted House", + "author_id": testUtils.NewDocIndex(2, 0), }, }, testUtils.CreateDoc{ CollectionID: 1, DocMap: map[string]any{ - "name": "Theif Lord", - "publisher_id": testUtils.NewDocIndex(0, 1), + "name": "Theif Lord", + "author_id": testUtils.NewDocIndex(2, 1), }, }, testUtils.CreateDoc{ - CollectionID: 2, + CollectionID: 0, DocMap: map[string]any{ - "name": "John Grisham", - "published_id": testUtils.NewDocIndex(1, 0), + "name": "Old Publisher", + "printed_id": testUtils.NewDocIndex(1, 0), }, }, testUtils.CreateDoc{ - CollectionID: 2, + CollectionID: 0, DocMap: map[string]any{ - "name": "Cornelia Funke", - "published_id": testUtils.NewDocIndex(1, 1), + "name": "New Publisher", + "printed_id": testUtils.NewDocIndex(1, 1), }, }, testUtils.Request{ @@ -156,31 +156,31 @@ func TestQueryOneToOneToOneSecondaryThenPrimary(t *testing.T) { }`, }, testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 2, DocMap: map[string]any{ - "name": "Painted House", - "publisher_id": testUtils.NewDocIndex(0, 0), + "name": "John Grisham", }, }, testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 2, DocMap: map[string]any{ - "name": "Theif Lord", - "publisher_id": testUtils.NewDocIndex(0, 1), + "name": "Cornelia Funke", }, }, testUtils.CreateDoc{ - CollectionID: 2, + CollectionID: 1, DocMap: map[string]any{ - "name": "John Grisham", - "published_id": testUtils.NewDocIndex(1, 0), + "name": "Painted House", + "publisher_id": testUtils.NewDocIndex(0, 0), + "author_id": testUtils.NewDocIndex(2, 0), }, }, testUtils.CreateDoc{ - CollectionID: 2, + CollectionID: 1, DocMap: map[string]any{ - "name": "Cornelia Funke", - "published_id": testUtils.NewDocIndex(1, 1), + "name": "Theif Lord", + "publisher_id": testUtils.NewDocIndex(0, 1), + "author_id": testUtils.NewDocIndex(2, 1), }, }, testUtils.Request{ @@ -248,29 +248,29 @@ func TestQueryOneToOneToOnePrimaryThenSecondary(t *testing.T) { `, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Old Publisher" - }`, + CollectionID: 1, + DocMap: map[string]any{ + "name": "Painted House", + }, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "New Publisher" - }`, + CollectionID: 1, + DocMap: map[string]any{ + "name": "Theif Lord", + }, }, testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, DocMap: map[string]any{ - "name": "Painted House", - "publisher_id": testUtils.NewDocIndex(0, 0), + "name": "Old Publisher", + "printed_id": testUtils.NewDocIndex(1, 0), }, }, testUtils.CreateDoc{ - CollectionID: 1, + CollectionID: 0, DocMap: map[string]any{ - "name": "Theif Lord", - "publisher_id": testUtils.NewDocIndex(0, 1), + "name": "New Publisher", + "printed_id": testUtils.NewDocIndex(1, 1), }, }, testUtils.CreateDoc{ @@ -302,20 +302,20 @@ func TestQueryOneToOneToOnePrimaryThenSecondary(t *testing.T) { Results: map[string]any{ "Publisher": []map[string]any{ { - "name": "Old Publisher", + "name": "New Publisher", "printed": map[string]any{ - "name": "Painted House", + "name": "Theif Lord", "author": map[string]any{ - "name": "John Grisham", + "name": "Cornelia Funke", }, }, }, { - "name": "New Publisher", + "name": "Old Publisher", "printed": map[string]any{ - "name": "Theif Lord", + "name": "Painted House", "author": map[string]any{ - "name": "Cornelia Funke", + "name": "John Grisham", }, }, }, diff --git a/tests/integration/query/one_to_one_to_one/with_order_test.go b/tests/integration/query/one_to_one_to_one/with_order_test.go index 4c241cc281..a5835c8527 100644 --- a/tests/integration/query/one_to_one_to_one/with_order_test.go +++ b/tests/integration/query/one_to_one_to_one/with_order_test.go @@ -40,43 +40,43 @@ func TestQueryOneToOneToOneWithNestedOrder(t *testing.T) { `, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "Old Publisher" - }`, + CollectionID: 2, + DocMap: map[string]any{ + "name": "John Grisham", + }, }, testUtils.CreateDoc{ - CollectionID: 0, - Doc: `{ - "name": "New Publisher" - }`, + CollectionID: 2, + DocMap: map[string]any{ + "name": "Cornelia Funke", + }, }, testUtils.CreateDoc{ CollectionID: 1, DocMap: map[string]any{ - "name": "Painted House", - "publisher_id": testUtils.NewDocIndex(0, 0), + "name": "Painted House", + "author_id": testUtils.NewDocIndex(2, 0), }, }, testUtils.CreateDoc{ CollectionID: 1, DocMap: map[string]any{ - "name": "Theif Lord", - "publisher_id": testUtils.NewDocIndex(0, 1), + "name": "Theif Lord", + "author_id": testUtils.NewDocIndex(2, 1), }, }, testUtils.CreateDoc{ - CollectionID: 2, + CollectionID: 0, DocMap: map[string]any{ - "name": "John Grisham", - "published_id": testUtils.NewDocIndex(1, 0), + "name": "Old Publisher", + "printed_id": testUtils.NewDocIndex(1, 0), }, }, testUtils.CreateDoc{ - CollectionID: 2, + CollectionID: 0, DocMap: map[string]any{ - "name": "Cornelia Funke", - "published_id": testUtils.NewDocIndex(1, 1), + "name": "New Publisher", + "printed_id": testUtils.NewDocIndex(1, 1), }, }, testUtils.Request{ diff --git a/tests/integration/schema/create_one_one_data_test.go b/tests/integration/schema/create_one_one_data_test.go new file mode 100644 index 0000000000..59ead8f5db --- /dev/null +++ b/tests/integration/schema/create_one_one_data_test.go @@ -0,0 +1,142 @@ +// Copyright 2024 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" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" +) + +func TestCreateOneToOne_Input_PrimaryObject(t *testing.T) { + test := testUtils.TestCase{ + Actions: []any{ + testUtils.SchemaUpdate{ + Schema: ` + type Book { + name: String + author: Author + } + + type Author { + name: String + wrote: Book @primary + } + `, + }, + testUtils.IntrospectionRequest{ + Request: ` + query { + __type (name: "AuthorMutationInputArg") { + name + inputFields { + name + type { + name + ofType { + name + kind + } + } + } + } + } + `, + ContainsData: map[string]any{ + "__type": map[string]any{ + "name": "AuthorMutationInputArg", + "inputFields": []any{ + map[string]any{ + "name": "name", + "type": map[string]any{ + "name": "String", + "ofType": nil, + }, + }, + map[string]any{ + "name": "wrote", + "type": map[string]any{ + "name": "ID", + "ofType": nil, + }, + }, + map[string]any{ + "name": "wrote", + "type": map[string]any{ + "name": "ID", + "ofType": nil, + }, + }, + }, + }, + }, + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +} + +func TestCreateOneToOne_Input_SecondaryObject(t *testing.T) { + test := testUtils.TestCase{ + Actions: []any{ + testUtils.SchemaUpdate{ + Schema: ` + type Book { + name: String + author: Author + } + + type Author { + name: String + wrote: Book @primary + } + `, + }, + testUtils.IntrospectionRequest{ + Request: ` + query { + __type (name: "BookMutationInputArg") { + name + inputFields { + name + type { + name + ofType { + name + kind + } + } + } + } + } + `, + ContainsData: map[string]any{ + "__type": map[string]any{ + "name": "BookMutationInputArg", + // Note: the secondary relation fields should not be here! + "inputFields": []any{ + map[string]any{ + "name": "name", + "type": map[string]any{ + "name": "String", + "ofType": nil, + }, + }, + }, + }, + }, + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/schema/updates/add/field/kind/doc_id_test.go b/tests/integration/schema/updates/add/field/kind/doc_id_test.go index be62192a1f..45b0471a81 100644 --- a/tests/integration/schema/updates/add/field/kind/doc_id_test.go +++ b/tests/integration/schema/updates/add/field/kind/doc_id_test.go @@ -72,7 +72,7 @@ func TestSchemaUpdatesAddFieldKindDocIDWithCreate(t *testing.T) { CollectionID: 0, Doc: `{ "name": "John", - "foo": "nhgfdsfd" + "foo": "bae-547eb3d8-7fc8-5c21-bcef-590813451e55" }`, }, testUtils.Request{ @@ -86,7 +86,7 @@ func TestSchemaUpdatesAddFieldKindDocIDWithCreate(t *testing.T) { "Users": []map[string]any{ { "name": "John", - "foo": "nhgfdsfd", + "foo": "bae-547eb3d8-7fc8-5c21-bcef-590813451e55", }, }, }, @@ -118,7 +118,7 @@ func TestSchemaUpdatesAddFieldKindDocIDSubstitutionWithCreate(t *testing.T) { CollectionID: 0, Doc: `{ "name": "John", - "foo": "nhgfdsfd" + "foo": "bae-547eb3d8-7fc8-5c21-bcef-590813451e55" }`, }, testUtils.Request{ @@ -132,7 +132,7 @@ func TestSchemaUpdatesAddFieldKindDocIDSubstitutionWithCreate(t *testing.T) { "Users": []map[string]any{ { "name": "John", - "foo": "nhgfdsfd", + "foo": "bae-547eb3d8-7fc8-5c21-bcef-590813451e55", }, }, }, diff --git a/tests/predefined/gen_predefined_test.go b/tests/predefined/gen_predefined_test.go index a32c261ce7..fc68681b4e 100644 --- a/tests/predefined/gen_predefined_test.go +++ b/tests/predefined/gen_predefined_test.go @@ -233,55 +233,6 @@ func TestGeneratePredefinedFromSchema_OneToOneToOnePrimary(t *testing.T) { } } -func TestGeneratePredefinedFromSchema_TwoPrimaryToOneMiddle(t *testing.T) { - schema := ` - type User { - name: String - device: Device - } - type Device { - model: String - owner: User @primary - specs: Specs @primary - } - type Specs { - OS: String - device: Device - }` - - docs, err := CreateFromSDL(schema, DocsList{ - ColName: "User", - Docs: []map[string]any{ - { - "name": "John", - "device": map[string]any{ - "model": "iPhone", - "specs": map[string]any{ - "OS": "iOS", - }, - }, - }, - }, - }) - assert.NoError(t, err) - - colDefMap, err := gen.ParseSDL(schema) - require.NoError(t, err) - - specsDoc := mustAddDocIDToDoc(map[string]any{"OS": "iOS"}, colDefMap["Specs"]) - userDoc := mustAddDocIDToDoc(map[string]any{"name": "John"}, colDefMap["User"]) - deviceDoc := mustAddDocIDToDoc(map[string]any{ - "model": "iPhone", - "specs_id": specsDoc[request.DocIDFieldName], - "owner_id": userDoc[request.DocIDFieldName], - }, colDefMap["Device"]) - - errorMsg := assertDocs([]map[string]any{userDoc, deviceDoc, specsDoc}, docs) - if errorMsg != "" { - t.Error(errorMsg) - } -} - func TestGeneratePredefinedFromSchema_OneToTwoPrimary(t *testing.T) { schema := ` type User {