diff --git a/schema/schema.go b/schema/schema.go index bf10a92..8f7dcca 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -114,11 +114,11 @@ type ForeignKeys struct { // Schema describes tabular data. type Schema struct { - Fields Fields `json:"fields,omitempty"` - PrimaryKeyPlaceholder interface{} `json:"primaryKey,omitempty"` - PrimaryKeys []string `json:"-"` - ForeignKeys ForeignKeys `json:"foreignKeys,omitempty"` - MissingValues []string `json:"missingValues,omitempty"` + Fields Fields `json:"fields,omitempty"` + PrimaryKeyPlaceholder interface{} `json:"primaryKey,omitempty"` + PrimaryKeys []string `json:"-"` + ForeignKeys []ForeignKeys `json:"foreignKeys,omitempty"` + MissingValues []string `json:"missingValues,omitempty"` } // GetField fetches the index and field referenced by the name argument. @@ -154,14 +154,17 @@ func (s *Schema) Validate() error { } } // Checking foreign keys. - for _, fk := range s.ForeignKeys.Fields { - if !s.HasField(fk) { - return fmt.Errorf("invalid foreign keys: there is no field %s", fk) + for _, fk := range s.ForeignKeys { + for _, f := range fk.Fields { + if !s.HasField(f) { + return fmt.Errorf("invalid foreign keys: there is no field %s", fk) + } + } + if len(fk.Reference.Fields) != len(fk.Fields) { + return fmt.Errorf("invalid foreign key: foreignKey.fields must contain the same number entries as foreignKey.reference.fields") } } - if len(s.ForeignKeys.Reference.Fields) != len(s.ForeignKeys.Fields) { - return fmt.Errorf("invalid foreign key: foreignKey.fields must contain the same number entries as foreignKey.reference.fields") - } + return nil } @@ -342,14 +345,16 @@ func (s *Schema) UnmarshalJSON(data []byte) error { return fmt.Errorf("primaryKey must be either a string or list") } a.PrimaryKeyPlaceholder = nil - if err := processPlaceholder(a.ForeignKeys.FieldsPlaceholder, &a.ForeignKeys.Fields); err != nil { - return fmt.Errorf("foreignKeys.fields must be either a string or list") - } - a.ForeignKeys.FieldsPlaceholder = nil - if err := processPlaceholder(a.ForeignKeys.Reference.FieldsPlaceholder, &a.ForeignKeys.Reference.Fields); err != nil { - return fmt.Errorf("foreignKeys.reference.fields must be either a string or list") + for i := range a.ForeignKeys { + if err := processPlaceholder(a.ForeignKeys[i].FieldsPlaceholder, &a.ForeignKeys[i].Fields); err != nil { + return fmt.Errorf("foreignKeys.fields must be either a string or list") + } + a.ForeignKeys[i].FieldsPlaceholder = nil + if err := processPlaceholder(a.ForeignKeys[i].Reference.FieldsPlaceholder, &a.ForeignKeys[i].Reference.Fields); err != nil { + return fmt.Errorf("foreignKeys.reference.fields must be either a string or list") + } + a.ForeignKeys[i].Reference.FieldsPlaceholder = nil } - a.ForeignKeys.Reference.FieldsPlaceholder = nil *s = Schema(a) return nil } @@ -359,7 +364,9 @@ func (s *Schema) MarshalJSON() ([]byte, error) { type schemaAlias Schema a := schemaAlias(*s) a.PrimaryKeyPlaceholder = a.PrimaryKeys - a.ForeignKeys.Reference.FieldsPlaceholder = a.ForeignKeys.Reference.Fields + for i := range a.ForeignKeys { + a.ForeignKeys[i].Reference.FieldsPlaceholder = a.ForeignKeys[i].Reference.Fields + } return json.Marshal(a) } diff --git a/schema/schema_test.go b/schema/schema_test.go index 4add379..de5c2b4 100644 --- a/schema/schema_test.go +++ b/schema/schema_test.go @@ -196,23 +196,23 @@ func TestRead_Sucess(t *testing.T) { }, { "FKFieldsString", - `{"fields":[{"name":"n1"}], "foreignKeys":{"fields":"n1"}}`, - Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: ForeignKeys{Fields: []string{"n1"}}}, + `{"fields":[{"name":"n1"}], "foreignKeys":[{"fields":"n1"}]}`, + Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: []ForeignKeys{{Fields: []string{"n1"}}}}, }, { "FKFieldsSlice", - `{"fields":[{"name":"n1"}], "foreignKeys":{"fields":["n1"]}}`, - Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: ForeignKeys{Fields: []string{"n1"}}}, + `{"fields":[{"name":"n1"}], "foreignKeys":[{"fields":["n1"]}]}`, + Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: []ForeignKeys{{Fields: []string{"n1"}}}}, }, { "FKReferenceFieldsString", - `{"fields":[{"name":"n1"}], "foreignKeys":{"reference":{"fields":"n1"}}}`, - Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: ForeignKeys{Reference: ForeignKeyReference{Fields: []string{"n1"}}}}, + `{"fields":[{"name":"n1"}], "foreignKeys":[{"reference":{"fields":"n1"}}]}`, + Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: []ForeignKeys{{Reference: ForeignKeyReference{Fields: []string{"n1"}}}}}, }, { "FKReferenceFieldsSlice", - `{"fields":[{"name":"n1"}], "foreignKeys":{"reference":{"fields":["n1"]}}}`, - Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: ForeignKeys{Reference: ForeignKeyReference{Fields: []string{"n1"}}}}, + `{"fields":[{"name":"n1"}], "foreignKeys":[{"reference":{"fields":["n1"]}}]}`, + Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: []ForeignKeys{{Reference: ForeignKeyReference{Fields: []string{"n1"}}}}}, }, { "Constraints", @@ -386,10 +386,10 @@ func TestValidate_SimpleValid(t *testing.T) { }{ {"PrimaryKey", Schema{Fields: []Field{{Name: "p"}, {Name: "i"}}, PrimaryKeys: []string{"p"}, - ForeignKeys: ForeignKeys{ + ForeignKeys: []ForeignKeys{{ Fields: []string{"p"}, Reference: ForeignKeyReference{Resource: "", Fields: []string{"i"}}, - }}, + }}}, }, } for _, d := range data { @@ -408,13 +408,18 @@ func TestValidate_Invalid(t *testing.T) { {"MissingName", Schema{Fields: []Field{{Type: IntegerType}}}}, {"PKNonexistingField", Schema{Fields: []Field{{Name: "n1"}}, PrimaryKeys: []string{"n2"}}}, {"FKNonexistingField", Schema{Fields: []Field{{Name: "n1"}}, - ForeignKeys: ForeignKeys{Fields: []string{"n2"}}, + ForeignKeys: []ForeignKeys{{Fields: []string{"n2"}}}, }}, + {"MissingReference", Schema{Fields: []Field{{Name: "n1"}}, + ForeignKeys: []ForeignKeys{{ + Fields: []string{"n1"}, + }}}, + }, {"InvalidReferences", Schema{Fields: []Field{{Name: "n1"}}, - ForeignKeys: ForeignKeys{ + ForeignKeys: []ForeignKeys{{ Fields: []string{"n1"}, Reference: ForeignKeyReference{Resource: "", Fields: []string{"n1", "n2"}}, - }}, + }}}, }, } for _, d := range data { @@ -430,7 +435,7 @@ func TestWrite(t *testing.T) { s := Schema{ Fields: []Field{{Name: "Foo", Constraints: Constraints{Unique: true}}, {Name: "Bar"}}, PrimaryKeys: []string{"Foo"}, - ForeignKeys: ForeignKeys{Reference: ForeignKeyReference{Fields: []string{"Foo"}}}, + ForeignKeys: []ForeignKeys{{Reference: ForeignKeyReference{Fields: []string{"Foo"}}}}, } buf := bytes.NewBufferString("") is.NoErr(s.Write(buf)) @@ -451,13 +456,15 @@ func TestWrite(t *testing.T) { "primaryKey": [ "Foo" ], - "foreignKeys": { - "reference": { - "fields": [ - "Foo" - ] + "foreignKeys": [ + { + "reference": { + "fields": [ + "Foo" + ] + } } - } + ] }` is.Equal(buf.String(), want)