HI Chad,

https://avro.apache.org/docs/++version++/specification/#names says: "The
empty string may also be used as a namespace to indicate the null
namespace."
That is, by using an empty string for the namespace you can help the
resolver to find the schema definition. I.e. you can use `name: ".Target"`
to say "I want to use the top-level Target schema"



On Wed, Jun 4, 2025 at 1:49 AM Chad Parry <c...@parry.org> wrote:

> It is possible to construct an ambiguous schema using the latest Avro
> specification. Before I file a JIRA issue, I want to check whether this
> is a known deficiency. I believe this is a bug in the specification, not
> any particular implementation.
>
> Types can be defined in the null namespace, and then those types can be
> referenced later. Such a reference would not contain any dots. For
> example, if we define the type "Target" in the null namespace, we can
> refer to it with the fullname "Target". However, the specification says
> that when a reference has no dot, "the namespace is the namespace of the
> enclosing definition." That means we could define a different type
> "Target" in the namespace "org.apache.avro". It could be referenced with
> the fullname "org.apache.avro.Target". If the enclosing namespace is
> already "org.apache.avro", then it could also be referenced with the
> simple name "Target". The problem arises when a single schema includes
> both those types, and "Target" is a valid reference to either one.
>
> In short, it is impossible to distinguish a qualified name that happens
> to be in the null namespace from a simple name. The specification
> creates this problem by neglecting the null namespace when it defines a
> fullname as "composed of two parts: a name and a namespace, separated by
> a dot."
>
> This could be solved by simply resolving all ambiguities in favor of the
> null namespace reference. For example, the reference "Target" should be
> interpreted as a fullname if such a type exists and as a simple name
> otherwise. If the author didn't intend to reference into the null
> namespace, then they can unambiguously use a fullname reference instead.
> Any solution will create compatibility concerns, so first I just want to
> discuss whether this is believed to be a problem.
>
> The following complete test case illustrates how this issue leads to
> data corruption with the Java API. Note that the Java implementation
> neither detects the ambiguity nor resolves it the way I am recommending.
>
>      @Test
>      void testAmbiguousReference() {
>          final Schema target = SchemaBuilder.builder()
>                  .record("Target")
>                  .doc("right")
>                  .fields()
>                  .endRecord();
>          final Schema decoy = SchemaBuilder.builder()
>                  .record(target.getName())
>                  .namespace("org.apache.avro")
>                  .doc("wrong")
>                  .fields()
>                  .endRecord();
>          final Schema ambiguous = SchemaBuilder.builder()
>                  .record("Ambiguous")
>                  .fields()
>                      .name("definition")
>                          .type(target)
>                          .noDefault()
>                      .name("working")
>                          .type(target)
>                          .noDefault()
>                      .name("enclosing")
>                          .type(SchemaBuilder.builder()
>                                  .record("Enclosing")
>                                  .namespace("org.apache.avro")
>                                  .fields()
>                                      .name("decoy")
>                                          .type(decoy)
>                                          .noDefault()
>                                      .name("working")
>                                          .type(decoy)
>                                          .noDefault()
>                                      .name("broken")
>                                          .type(target)
>                                          .noDefault()
>                                  .endRecord())
>                          .noDefault()
>                  .endRecord();
>          final Schema parsed = new Schema.Parser().parse(
>                  ambiguous.toString());
>          // This assertion succeeds.
>          Assertions.assertEquals(
>                  ambiguous.getField("working").schema(),
>                  parsed.getField("working").schema());
>          // This assertion succeeds but the specification is unclear.
>          Assertions.assertEquals(
>                  ambiguous.getField("enclosing").schema()
>                          .getField("working").schema(),
>                  parsed.getField("enclosing").schema()
>                          .getField("working").schema());
>          // This assertion FAILS.
>          Assertions.assertEquals(
>                  ambiguous.getField("enclosing").schema()
>                          .getField("broken").schema(),
>                  parsed.getField("enclosing").schema()
>                          .getField("broken").schema());
>      }
>
> The assertion failure message complains:
> expected: <{"type":"record","name":"Target","doc":"right","fields":[]}>
> but was:
>
> <{"type":"record","name":"Target","namespace":"org.apache.avro","doc":"wrong","fields":[]}>
>
>

Reply via email to