Skip to content

Commit

Permalink
Support absolute name type references.
Browse files Browse the repository at this point in the history
When we have schemas that reference schemas in a different
packages, you use the full dotted path name to reference the type.

Support these paths during schema import.
  • Loading branch information
James Crasta committed Apr 6, 2016
1 parent 415d6fa commit a258996
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 8 deletions.
16 changes: 14 additions & 2 deletions schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io/ioutil"
"math"
"reflect"
"strings"
)

const (
Expand Down Expand Up @@ -957,7 +958,14 @@ func schemaByType(i interface{}, registry map[string]Schema, namespace string) (
case typeString:
return new(StringSchema), nil
default:
schema, ok := registry[getFullName(v, namespace)]
// If a name reference contains a dot, we consider it a full name reference.
// Otherwise, use the getFullName helper to look up the name.
// See https://avro.apache.org/docs/1.7.7/spec.html#Names
fullName := v
if !strings.ContainsRune(fullName, '.') {
fullName = getFullName(v, namespace)
}
schema, ok := registry[fullName]
if !ok {
return nil, fmt.Errorf("Unknown type name: %s", v)
}
Expand Down Expand Up @@ -1002,6 +1010,10 @@ func schemaByType(i interface{}, registry map[string]Schema, namespace string) (
return parseFixedSchema(v, registry, namespace)
case typeRecord:
return parseRecordSchema(v, registry, namespace)
default:
// Type references can also be done as {"type": "otherType"}.
// Just call back in so we can handle this scenario in the string matcher above.
return schemaByType(v[schemaTypeField], registry, namespace)
}
case []interface{}:
return parseUnionSchema(v, registry, namespace)
Expand Down Expand Up @@ -1128,7 +1140,7 @@ func addSchema(name string, schema Schema, schemas map[string]Schema) Schema {
}

func getFullName(name string, namespace string) string {
if len(namespace) > 0 {
if len(namespace) > 0 && !strings.ContainsRune(name, '.') {
return namespace + "." + name
}

Expand Down
30 changes: 24 additions & 6 deletions schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,13 +260,21 @@ func TestFixedSchema(t *testing.T) {
}

func TestSchemaRegistryMap(t *testing.T) {
rawSchema1 := `{"type": "record", "name": "TestRecord", "fields": [
{"name": "longRecordField", "type": "long"}
]}`
rawSchema1 := `{"type": "record", "name": "TestRecord", "namespace": "com.github.elodina", "fields": [
{"name": "longRecordField", "type": "long"}
]}`

rawSchema2 := `{"type": "record", "name": "TestRecord2", "fields": [
{"name": "record", "type": ["null", "TestRecord"]}
]}`
rawSchema2 := `{"type": "record", "name": "TestRecord2", "namespace": "com.github.elodina", "fields": [
{"name": "record", "type": ["null", "TestRecord"]}
]}`

rawSchema3 := `{"type": "record", "name": "TestRecord3", "namespace": "com.github.other", "fields": [
{"name": "record", "type": ["null", "com.github.elodina.TestRecord2"]}
]}`

rawSchema4 := `{"type": "record", "name": "TestRecord3", "namespace": "com.github.elodina", "fields": [
{"name": "record", "type": ["null", {"type": "TestRecord2"}, "com.github.other.TestRecord3"]}
]}`

registry := make(map[string]Schema)

Expand All @@ -279,6 +287,16 @@ func TestSchemaRegistryMap(t *testing.T) {
assert(t, err, nil)
assert(t, s2.Type(), Record)
assert(t, len(registry), 2)

s3, err := ParseSchemaWithRegistry(rawSchema3, registry)
assert(t, err, nil)
assert(t, s3.Type(), Record)
assert(t, len(registry), 3)

s4, err := ParseSchemaWithRegistry(rawSchema4, registry)
assert(t, err, nil)
assert(t, s4.Type(), Record)
assert(t, len(registry), 4)
}

func TestRecordCustomProps(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func assert(t *testing.T, actual interface{}, expected interface{}) {
if !reflect.DeepEqual(actual, expected) {
_, fn, line, _ := runtime.Caller(1)
t.Errorf("Expected %v, actual %v\n@%s:%d", expected, actual, fn, line)
t.FailNow()
}
}

Expand Down

0 comments on commit a258996

Please sign in to comment.