-
Notifications
You must be signed in to change notification settings - Fork 110
Adopt dataType for Literals and preparedValues #3395
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
base: 4.2.4-release
Are you sure you want to change the base?
Conversation
0e56d68
to
bdc3827
Compare
def373f
to
0630175
Compare
0630175
to
582bd0e
Compare
import io.prometheus.client.CollectorRegistry; | ||
import org.apache.logging.log4j.LogManager; |
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.
please revert.
@@ -235,49 +234,33 @@ public Response execute(String database, String schema, String sql, List<Paramet | |||
|
|||
private static void addPreparedStatementParameter(RelationalPreparedStatement relationalPreparedStatement, | |||
Parameter parameter, int index) throws SQLException { |
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.
Can you please add @Nonnull
annotations where applicable to this method signature?
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.
done!
@@ -106,6 +106,7 @@ message Parameter { | |||
// Reuse the column type here. It has much of what we need carrying | |||
// across parameters as well as null support, etc. | |||
Column parameter = 2; | |||
Type type = 3; |
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.
Can we remove the java_sql_types_code
above? the mapping between Type
and java SQL type is hardcoded in the codebase, and so it is redundant here, right?
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.
We cannot actually remove the java_sql_types_code
straightaway - otherwise mixed-mode testing will start breaking as they still populate the java_sql_types_code
field. Part of the code in JDBC deals with using the new Types, if available, otherwise fall to sql types.
We can probably remove sql types in futue release though.
// Indicates a column that isn't part of the DDL for a query, but is part of the returned | ||
// tuple (and therefore necessary to keep so that our positional ordering is intact) | ||
bool phantom = 5; | ||
// If this column has a Struct or an Array, their metadata is here. | ||
oneof metadata { | ||
ListColumnMetadata structMetadata = 6; | ||
ColumnMetadata arrayMetadata = 7; | ||
EnumMetadata enumMetadata = 8; |
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.
please adapt the comment at line 55.
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.
done!
@@ -26,20 +26,39 @@ option java_multiple_files = true; | |||
option java_package = "com.apple.foundationdb.relational.jdbc.grpc.v1.column"; | |||
option java_outer_classname = "ColumnProto"; | |||
|
|||
enum Type { | |||
NO_TYPE = 0; |
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.
UNKNOWN?
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.
I think I am fine with UNKNOWN
- just that my early idea came from the fact that there will be no type supplied by older versions.
|
||
final List<Object> elements = new ArrayList<>(); | ||
|
||
@Override | ||
public EmbeddedRelationalStruct build() { | ||
return new ImmutableRowStruct(new ArrayRow(elements.toArray()), new RelationalStructMetaData(fields.toArray(new FieldDescription[0]))); | ||
// Ideally, the name of the struct should be something that the user can specify, however, this actually |
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 is already an open issue about this. The struct building and verification is something the client, and the structure name should be something the user can specify as well.
} | ||
|
||
@Override | ||
public Struct createStruct(String typeName, Object[] attributes) throws SQLException { | ||
// We do not preserve the typeName, as there is no validation around that currently. | ||
final var builder = EmbeddedRelationalStruct.newBuilder(); |
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.
I do like the simplification, nice work.
@@ -240,8 +240,6 @@ public RelationalArray getArray(int oneBasedPosition) throws SQLException { | |||
for (final var t : coll) { | |||
if (t instanceof Message) { | |||
elements.add(new ImmutableRowStruct(new MessageTuple((Message) t), arrayMetaData.getElementStructMetaData())); | |||
} else if (t instanceof ByteString) { |
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.
I see that in MessageTuple.sanitizeField
we return ByteString::toByteArray()
when encountering a ByteString
object. However, in this else if
branch I see that you removed the dispatch on ByteString
without sanitizing t
, is this expected? Perhaps it is called indirectly above but I am not sure.
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. The hidden contract here is that whatever comes out of MessageTuple#getObjectInternal
, is already sanitised, which is depicted by the altered logic here. However, I had to "sanitise" for a special case when we think its a Message
but is actually a special-cased nullable wrapper. For this particular case, we will have to sanitise the "repeated" field (content of that array).
} | ||
return expression; | ||
if (resultType.isArray() && value instanceof AbstractArrayConstructorValue) { |
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.
You should check whether the promotion is necessary in case of arrays as well, otherwise, a new LightArrayConstructorValue
is constructed, potentially unnecessarily.
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.
nice catch!
fdb-relational-api/src/main/java/com/apple/foundationdb/relational/api/StructMetaData.java
Show resolved
Hide resolved
if (this.isNullable() != otherStructType.isNullable() || fields.size() != otherFields.size()) { | ||
return false; | ||
} | ||
for (int i = 0; i < fields.size(); i++) { |
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.
This is not exactly correct. If the other structure has more fields it would still pass although it shouldn't I think.
} catch (SQLException e) { | ||
throw new RelationalException(e).toUncheckedWrappedException(); | ||
DataType distinctType = null; | ||
for (var object: objects) { |
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.
This is not entirely correct I think in the presence of nullable fields.
@@ -66,9 +74,16 @@ class RelationalArrayFacade implements RelationalArray { | |||
|
|||
RelationalArrayFacade(@Nonnull ColumnMetadata delegateMetadata, Array array) { | |||
this.delegateMetadata = delegateMetadata; | |||
this.type = Suppliers.memoize(this::computeType); |
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 is almost always a good idea to memoize repeated computations, but I think this should be pushed to the underlying delegate
if possible (since this class is a mere facade presumably).
@Nonnull | ||
@Override | ||
public DataType.StructType getRelationalDataType() throws SQLException { | ||
throw new SQLException("Not implemented", ErrorCode.UNSUPPORTED_OPERATION.getErrorCode()); |
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.
Can we implement this?
var listColumnMetadataBuilder = ListColumnMetadata.newBuilder(); | ||
for (int oneBasedIndex = 1; oneBasedIndex <= metadata.getColumnCount(); oneBasedIndex++) { | ||
var columnMetadata = toColumnMetadata(metadata, oneBasedIndex); | ||
var columnMetadata = toColumnMetadata(metadata, oneBasedIndex, oneBasedIndex - 1 + metadata.getLeadingPhantomColumnCount()); |
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.
was this wrong all the time (in the presence of phantom columns, that is)?
This PR moves away from using
java.sql.Types
in the internals offdb-relational-core
, while still maintaining JDBC-compliance for externalgetType()
-like operations. It is replaced withDataType
, which provides richer and more diverse type information available for downstream operations. Notably, we can now have types likeUuid
,Enum
,Version
expressed natively. There are several consequences of this:StructMetadata
andArrayMetadata
wrapDataType
as the source of truth for their type info. However, they still map tosql.Types
externally. Moreover, they now exposegetRelationalDataType()
that returnsDataType
to the external users for more transparency.grpc
protobufs now have aType
enum, moving away fromsql.Types
too. This was needed to supportstruct
andarray
operations homogenously across embedded and JDBC drivers. It keeps the old types too for backward compatibility, which I think should be removed in future to simplify conversions.