-
Notifications
You must be signed in to change notification settings - Fork 114
Rollback UUID support in SQL Layer #3293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few extra tests that this could probably use. My main question is whether this sets us up well for future work that will use UUIDs, and I'm not sure. In particular, using the message type in MessageTuple means that we can't base the decision on the query plan, which I think will have negative implications on query semantics with continuations.
| } else if (TupleFieldsProto.UUID.getDescriptor().equals(messageDescriptor)) { | ||
| return Type.uuidType(isNullable); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we just did this revert here and the test changes (and maybe the parser changes), would that be sufficient? Maybe we'd also need to change the way a MessageTuple gets interpreted so that it choses whether to return a struct or UUID based on the type information.
I'm thinking that because the main problem we're trying to solve is that the new Tuple.UUID primitive type was appearing in plans, which means that plans weren't continuable between 4.2.3.0 and earlier, and reverting this line here makes it so that when we generate the Types from the meta-data, we don't use the new UUID type. But leaving the getUuid and setUuid implementations would prepare clients for the future, in that when we enable this line (in say 4.3), they'd be able to use the client to access UUID fields correctly.
Regardless, do we have any direct tests showing what the Type of a UUID field will be interpreted as? I think we may get that indirectly from the new yaml test, but it may be good to have an explicit test of that somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that makes sense. We will indeed need to change the way message translation happens for UUID, which is expected to return struct for UUID if the returned type is STRUCT (old versions) and return a JAVA UUID if the return type is sql.Types.OTHER (since there is no explicit UUID in sql.Types). To achieve this, I have a temporary fix in RowStruct that returns the expected type and supposedly handles both the cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regardless, do we have any direct tests showing what the Type of a UUID field will be interpreted as? I think we may get that indirectly from the new yaml test, but it may be good to have an explicit test of that somewhere.
Added in TypeTest.java
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not a bad test, but I was actually thinking more of a test that would show that the ResultSet returns a UUID or a struct, as appropriate. I have some thoughts in the other comment I left here, but the kind of test I was thinking of may be a bit more work than we'd like.
...elational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java
Show resolved
Hide resolved
| connect: "jdbc:embed:/FRL/UUID_PROTO_YAML?schema=UUID_PROTO_SCHEMA" | ||
| tests: | ||
| - | ||
| # test select * |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to have a test where more than one record is returned, as that's going to be more useful for testing continuations. The most interesting scenarios for that probably happen between this and a hypothetical future version that re-enables UUIDs, but if I'm right, the continuations for that one will be a bit weird in that they should alternate between structs and UUIDs based on the version chosen for each request, not just the starting version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, thats right. The future version that brings back UUID will not be compatible with older version when that is executing first for the reason you mentioned.
| return getArray(oneBasedPosition); | ||
| case Types.BINARY: | ||
| return getBytes(oneBasedPosition); | ||
| case Types.OTHER: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I'm still trying to piece this together, but I think this works. If I'm understanding the intent of this function, it seems to be that it:
- Given a field position, looks up the column type of the field
- For a UUID, that meta-data may return that it's a
STRUCT(in which case we get a nested message back) or anOTHER, in which case we look at whether the field is aTupleFieldsProto.UUIDand then parse it as a UUID if so - The struct meta-data that this uses comes from the query plan's
Type, which for plans coming from a continuation, will match the value coming from the serialized plan:Line 376 in ee8f327
return new RecordLayerResultSet(metaData, iterator, connection,
Which I think means that this should do what we expect, and should allow us to, for each execution of a run with a UUID type, either get UUIDs back or get structs back based on the type chosen by the plan's Type information.
It would be nice if we had some kind of test that that would work, but the only thing I can think of would be to take an existing plan with a UUID-as-struct, and then manually update the Type information to use the new UUID primitive type.
A different approach might be to re-enable 4.2.4.0 or 4.2.3.0 locally, and then run the uuidProto tests. They should fail, but they should fail in a way that let's us consistently return UUIDs if the initial version is below !current_version. We'd need to revert that change, though, before checking it in.
If this is wrong, I think this is something that we'd figure out in the future when we re-enable UUIDs (say, in 4.3). So, we could just say that we'll proceed for now under the assumption that this works, and then make adjustments if that ends up not being the case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. That's my thinking.
I actually tested locally, with 4.2.3.0 both ways, 4.2.3.0 -> current & the other way round, and it seems to be working as expected for 4.2.3.0 -> current, but not for current -> 4.2.3.0. The reason for failure of the later is again related to the fact that in 4.2.3.0 the conversion from TupleFieldsProto.UUID message -> JAVA UUID happens without checking the expected type. This is something that we should fix in future version to maintain backward compatibility with !current_version.
As you mentioned, I cannot includ these tests in PR since it doesn't entirely pass, but have tested locally satisfactorily and with additional test suites.
| } else if (TupleFieldsProto.UUID.getDescriptor().equals(messageDescriptor)) { | ||
| return Type.uuidType(isNullable); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not a bad test, but I was actually thinking more of a test that would show that the ResultSet returns a UUID or a struct, as appropriate. I have some thoughts in the other comment I left here, but the kind of test I was thinking of may be a bit more work than we'd like.
This PR reverts the SQL layer support for UUID that was introduced in #3198. However, the Record Layer support for UUID stays as it is. This makes this compatible with releases <
4.2.3.0which was required to maintain plan continuation compatibility for plans serialized with non-UUID Type.Also adds a yaml-test for explicitly defining the RecordMetadata using proto, and using the
TupleField.UUIDmessage in it. Owing to difference in behavior in how this and versions (4.2.3.0 and 4.2.4.0) interpretsTupleField.UUID, this PR also blocklists these versions from yaml-testing.fixes: #3285