Skip to content

Conversation

@bellemare
Copy link
Contributor

@bellemare bellemare commented Mar 11, 2018

  • Added Defaults to Enums.
  • Enum Defaults are only applied to values which don't match the Reader Enum symbols.
  • Enum Defaults do not override any Field Default behaviour. Field Defaults are used when a reader reads a datum that does not have the Field defined (as is current behaviour).

To see an example table of this behaviour, see Final Default & Fallback tab in:
https://docs.google.com/spreadsheets/d/1YkTBnHCBPGz2t0gQI3OioKS_xP9h9lq_a-gS2jSGFAc/edit?usp=sharing

Copy link
Contributor

@cutting cutting left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great. I like the simple, minimal approach taken. I've identified a few improvements, namely builder and IDL integration. These could be done as followup issues, but it might be better to get them in from the start. Thanks!

&& symbols.equals(that.symbols)
&& props.equals(that.props);
}
public String getEnumDefault() { return enumDefault; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs @OverRide?

if (aliases.containsKey(name))
result = Schema.createEnum(aliases.get(name).full, s.getDoc(), null,
s.getEnumSymbols());
s.getEnumSymbols(), s.getEnumDefault());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I scanned for other places where Schema.createEnum is called to see which need updates.
ResolvingVisitor.java also needs this same change. This is used to support IDL. We should also add support to IDL for enum defaults.
SchemaBuilder.java should be changed to permit specifying an enum default.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay yes, I can add that to this PR.

@cutting
Copy link
Contributor

cutting commented Apr 16, 2018

Here's a fix for the IDL problem. The grammar change seems to cause the parser to lookahead farther, so the last documentation comment that's been seen is too far along. I changed it to grab the doc string once it's seen the enum keyword and that seems to fix it.

+++ b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj
@@ -1102,12 +1102,12 @@ Schema EnumDeclaration():
   String defaultSymbol = null;
 }
 {
-  "enum"
+  "enum" {   String doc = getDoc(); }
   name = Identifier()
   symbols = EnumBody()
       [ <EQUALS> defaultSymbol=Identifier() <SEMICOLON>]
   {
-    Schema s = Schema.createEnum(name, getDoc(), this.namespace, symbols,
+    Schema s = Schema.createEnum(name, doc, this.namespace, symbols,
                                  defaultSymbol);
     names.put(s.getFullName(), s);
     return s;

Patch otherwise looks good. We should also test the IDL change. Maybe change simple.avdl to specify an enum default, then update simple.avpr to contain the new output? (You can use 'mvn package -dskipTests' to create a tools.jar so 'java -jar tools.jar idl ...' can be used to create the new compiler test output file.)

…ing. Added test case to simple.avdl and simple.avpr
@bellemare
Copy link
Contributor Author

@cutting - Thanks Doug. I applied the patch, added a test and built the tooling to validate that it works. Is there anything else you forsee being required? Also, do we need additional eyes on this? I recall that someone mentioned in the JIRA thread about the "@default" annotation - I don't have any idea how it would interact with this.

@cutting
Copy link
Contributor

cutting commented Apr 18, 2018

We're almost there. I just looked at the builder integration, and think it would be better if we instead added defaultSymbol(String) method to EnumBuilder. We also need javadoc for this new method, and should update the EnumBuilder example in the SchemaBuilder class javadoc to specify a default symbol.

Also, we need to update doc/src/content/xdocs/idl.xml to describe enum defaults. This can be in the "Defining and Enumeration" section. We can update the example to include a default.

Additional eyes are not required. Folks have the opportunity to follow here & object. I'll commit this once we're happy with it. We could add an @default annotation now, or commit this now and add that later, I don't have a strong feeling.

@BirdHowl
Copy link

We could add an @default annotation now, or commit this now and add that later, I don't have a strong feeling.

I think there's some misunderstanding here - @default already works, since IDL lets any JSON property be set through annotations (although that behavior isn't well-documented). Anything that doesn't work as an annotation doesn't work because of being a reserved property. default, however is a reserved property only for fields.

If I take this a protocol file named test.avdl:

protocol Test {
  @default("UNKNOWN")
  enum Status {
      SUCCESS,
      FAILURE,
      UNKNOWN
  }
}

And then run avro-tools.jar idl test.avdl (tested on both this branch and master), I get this output:

{
  "protocol" : "Test",
  "namespace" : null,
  "types" : [ {
    "type" : "enum",
    "name" : "Status",
    "symbols" : [ "SUCCESS", "FAILURE", "UNKNOWN" ],
    "default" : "UNKNOWN"
  } ],
  "messages" : { }
}

In my JIRA post, I was attempting to provide reasonable answers to the question: "how should we handle cases when both @default and the new = syntax are present."

(Currently on this branch, if I use both I get JSON like:

{
  "protocol" : "Test",
  "namespace" : null,
  "types" : [ {
    "type" : "enum",
    "name" : "Status",
    "symbols" : [ "SUCCESS", "FAILURE", "UNKNOWN" ],
    "default" : "FAILURE",
    "default" : "UNKOWN"
  } ],
  "messages" : { }
}

)

Adam Bellemare added 2 commits April 27, 2018 22:33
…hat the @default annotation no longer works on enum avdl definitions. Updated the way that SchemaBuilder allows an enum to be built sith a default by separating out the default setter.
Schema expected = Schema.createEnum("myenum", null, null, symbols, enumDefault);
expected.addProp("p", "v");
Schema schema = SchemaBuilder.enumeration("myenum")
.prop("p", "v").defaultSymbol(enumDefault).symbols("a", "b");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this particular code decision means that the default must be set before calling .symbols(). It will not work the other way around.

Set reserved = SCHEMA_RESERVED;
if (type.equals("enum")) {
reserved = ENUM_RESERVED;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention here was to not cause any unintended side effects.

@bellemare
Copy link
Contributor Author

One more quick statement - I noticed that there is next to no testing around the usage of the "@default" notation. I know that my changes work only because I cannot use the "@default" notation on my enums anymore. However, I do not have any tests to prove that. Should this also be part of this JIRA?

Iterator<String> i = schema.getFieldNames();

Set reserved = SCHEMA_RESERVED;
if (type.equals("enum")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test should instead be 'type == ENUM', no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just kept it consistent with the other references to it in this file. See line 1274 and 1330. "type" is actually a string here, believe it or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I somehow tagged the wrong line. I meant line 105, not this one.

<source>
enum Shapes {
SQUARE, TRIANGLE, CIRCLE
} = CIRCLE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a semicolon. I don't know if that's the best syntax, but it is what we implemented!

@cutting
Copy link
Contributor

cutting commented May 1, 2018

As far as @default, I think it's probably a bug that this was not a reserved word in IDL from the start. We could fix that, but it might break folks who've relied on it (although you could not have used it to set field defaults previously, only to provide a property named "default" on other kinds of schemas). So only breaking folks who used it on enums is probably best, since we're changing the semantics of that case anyway. Does that seem reasonable?

@bellemare
Copy link
Contributor Author

bellemare commented May 1, 2018

My preference is to impose a minimal change centered around the functionality. In this case I would prefer to leave the @default behaviour as it currently is except for changing it for enum. That being said, I would be happy to file a bug ticket for it as a separate fix - that way if there is a bunch of issues with it that it would be addressable on its own and not affect this commit.

@cutting
Copy link
Contributor

cutting commented May 1, 2018

It sounds like we agree about @default. With the current patch its behavior is only changed for enums, and that this is appropriate.

Copy link
Contributor

@cutting cutting left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once the semicolon is added to the example in the documentation, I'm ready to commit this.

<source>
enum Shapes {
SQUARE, TRIANGLE, CIRCLE
} = CIRCLE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need a semicolon at EOL

@cutting cutting merged commit 238714d into apache:master May 2, 2018
@bellemare
Copy link
Contributor Author

@cutting Thanks for your help Doug, I really appreciate all the feedback and assistance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants