-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Add an optional JDBC connector type mapping to varchar #186
Conversation
BTW if we treat an unsupported type as a varchar
|
6e99107
to
b1a19a6
Compare
AFAIK most of the use-cases with such non-standard types in Presto are for reading and extracting needed values for analytic processing to gain valuable insights. |
b1a19a6
to
62405ff
Compare
I suggest to change the parameter name to
|
@guyco33 i don't fully understand. |
@findepi nonstandard_types are all the types that are not implemented in |
Maybe it will be better to define it with 2 parameters like this:
When |
I don't think this is a sufficient definition.
This is intersting idea. Actually, this could be simplified (we don't need to have two parameters):
some concerns:
|
@findepi
For example: |
a105792
to
503a36b
Compare
73b057e
to
2562c56
Compare
2562c56
to
ce0829e
Compare
e1bede8
to
da4019d
Compare
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.
As discussed offline:
I would strongly prefer this mapping to be done based on JdbcTypeHandle#jdbcTypeName
only, so that we have one, easy to understand configuration toggle.
da4019d
to
edee55b
Compare
Using jdbcTypeName only might not be sufficient for RDBMS connectors with types without names. |
@guyco33 i am aware of this. |
@guyco33 thanks for checking. So the plan would be:
|
edee55b
to
dfcc52c
Compare
d218031
to
774c50c
Compare
774c50c
to
22f973c
Compare
22f973c
to
68140a1
Compare
163903f
to
e26d20f
Compare
f49eb88
to
2867771
Compare
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.
LGTM
{ | ||
if (jdbcTypesMappedToVarchar != null) { | ||
for (String type : jdbcTypesMappedToVarchar.split(",")) { | ||
this.jdbcTypesMappedToVarchar.add(type.trim()); |
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 reset
jdbcTypesMappedToVarchar
when setter is called. - avoid
String#split
for all its weirdnesses
this.jdbcTypesMappedToVarchar = ImmutableSet.copyOf(Splitter.on(",").omitEmptyStrings().split(nullToEmpty(jdbcTypesMappedToVarchar)));
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.
Whops.. add .trimResults()
too.
{ | ||
this.identifierQuote = requireNonNull(identifierQuote, "identifierQuote is null"); | ||
this.connectionFactory = requireNonNull(connectionFactory, "connectionFactory is null"); | ||
requireNonNull(caseInsensitiveNameMatchingCacheTtl, "caseInsensitiveNameMatchingCacheTtl is null"); | ||
|
||
this.caseInsensitiveNameMatching = caseInsensitiveNameMatching; | ||
this.jdbcTypesMappedToVarchar = jdbcTypesMappedToVarchar; |
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.jdbcTypesMappedToVarchar = jdbcTypesMappedToVarchar; | |
this.jdbcTypesMappedToVarchar = ImmutableSet.copyOf(requireNonNull(jdbcTypesMappedToVarchar, "jdbcTypesMappedToVarchar is null")); |
@@ -125,20 +126,23 @@ public BaseJdbcClient(BaseJdbcConfig config, String identifierQuote, ConnectionF | |||
identifierQuote, | |||
connectionFactory, | |||
requireNonNull(config, "config is null").isCaseInsensitiveNameMatching(), | |||
config.getCaseInsensitiveNameMatchingCacheTtl()); | |||
config.getCaseInsensitiveNameMatchingCacheTtl(), | |||
config.getJdbcTypesMappedToVarchar()); |
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.
move the new arg right after identifierQuote
and connectionFactory
(same in assignments below)
(i'm aware the identifierQuote
and connectionFactory
are misordered)
@@ -47,6 +51,22 @@ public BaseJdbcConfig setConnectionUrl(String connectionUrl) | |||
return this; | |||
} | |||
|
|||
public Set<String> getJdbcTypesMappedToVarchar() |
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.
Add getter/setter in same order you added the field (ie field is last, so move getter/setter to the end of the class)
{ | ||
if (jdbcTypesMappedToVarchar.contains(type.getJdbcTypeName().get())) { |
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.
don't fail when type.getJdbcTypeName()
is empty
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 won't fail since jdbcTypesMappedToVarchar
doesn't contain empty strings
|
||
assertEquals(expected.getJdbcTypesMappedToVarchar().contains("mytype"), true); | ||
assertEquals(expected.getJdbcTypesMappedToVarchar().contains("struct_type1"), true); | ||
assertEquals(expected.getJdbcTypesMappedToVarchar().contains("supported_type"), false); |
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.
assertEquals(expected.getJdbcTypesMappedToVarchar().contains("supported_type"), false); | |
assertEquals(expected.getJdbcTypesMappedToVarchar(), ImmutableSet.of("mytype", "struct_type1")); |
@@ -260,7 +264,7 @@ public BaseJdbcClient( | |||
@Override | |||
public Optional<ColumnMapping> toPrestoType(ConnectorSession session, Connection connection, JdbcTypeHandle typeHandle) | |||
{ | |||
return jdbcTypeToPrestoType(session, typeHandle); | |||
return jdbcTypeToPrestoType(session, typeHandle, jdbcTypesMappedToVarchar); |
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 should be handled before calling jdbcTypeToPrestoType
, so let's keep it inside JdbcClient and don't change that method.
Since the mapping is not that trivial (eg disabling predicate pushdown), I think a helper method could be useful.
It could be used like that:
Optional<ColumnMapping> mapping = getForcedMappingToVarchar(typeHandle);
if (mapping.isPresent()) {
return mapping;
}
where getForcedMappingToVarchar
is defined in BaseJdbcClient:
protected Optional<...> getForcedMappingToVarchar(...) { ... }
@@ -33,6 +36,7 @@ | |||
private boolean caseInsensitiveNameMatching; | |||
private Duration caseInsensitiveNameMatchingCacheTtl = new Duration(1, MINUTES); | |||
private CredentialProviderType credentialProviderType = INLINE; | |||
private Set<String> jdbcTypesMappedToVarchar = new HashSet<>(); |
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.
private Set<String> jdbcTypesMappedToVarchar = new HashSet<>(); | |
private Set<String> jdbcTypesMappedToVarchar = ImmutableSet.of(); |
@@ -122,7 +123,8 @@ public PhoenixClient(PhoenixConfig config, ConnectionFactory connectionFactory) | |||
ESCAPE_CHARACTER, | |||
connectionFactory, | |||
config.isCaseInsensitiveNameMatching(), | |||
config.getCaseInsensitiveNameMatchingCacheTtl()); | |||
config.getCaseInsensitiveNameMatchingCacheTtl(), | |||
new HashSet<>()); |
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.
new HashSet<>()); | |
ImmutableSet.of()); |
@@ -261,6 +263,9 @@ protected ResultSet getTables(Connection connection, Optional<String> schemaName | |||
String jdbcTypeName = typeHandle.getJdbcTypeName() | |||
.orElseThrow(() -> new PrestoException(JDBC_ERROR, "Type name is missing: " + typeHandle)); | |||
|
|||
if (jdbcTypesMappedToVarchar.contains(jdbcTypeName)) { |
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 needs to be added to MySqlClient and SqlServerClient as well, since they too override toPrestoType()
this.includeTypeNamesMappingToVarchar = new HashSet<String>(); | ||
if (typesMappedToVarcharInclude != null) { | ||
for (String type : typesMappedToVarcharInclude.split(",")) { | ||
if (typesMap.containsKey(type.toUpperCase())) { |
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.
toUpperCase(ENGLISH)
here and below
this.typesMappedToVarcharInclude = typesMappedToVarcharInclude; | ||
this.includeTypesMappingToVarchar = new HashSet<Integer>(); | ||
this.includeTypeNamesMappingToVarchar = new HashSet<String>(); | ||
if (typesMappedToVarcharInclude != null) { |
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.
invert the condition, that way you will avoid long nested blocks
private Set<Integer> includeTypesMappingToVarchar; | ||
private Set<String> includeTypeNamesMappingToVarchar; | ||
private Set<Integer> excludeTypesMappingToVarchar; | ||
private Set<String> excludeTypeNamesMappingToVarchar; |
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 would extract these collection of the config classes to some new entity like MappingToVarchar
. IMO config should not have any logic.
@@ -115,6 +115,7 @@ | |||
|
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 add "end-to-end" test where you SELECT unsupported type as varchar. Maybe to io.prestosql.plugin.jdbc.TestJdbcIntegrationSmokeTest
or somewhere close.
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.
A test in TestPostgreSqlTypeMapping
would be nice too.
} | ||
} | ||
} | ||
}; |
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 squash the commits. Changes in single PR should not go back and forth.
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.
:) sorry @kokosing i didn't warn you this has significantly altered since the beginning
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.identifierQuote = requireNonNull(identifierQuote, "identifierQuote is null"); | ||
this.connectionFactory = requireNonNull(connectionFactory, "connectionFactory is null"); | ||
requireNonNull(caseInsensitiveNameMatchingCacheTtl, "caseInsensitiveNameMatchingCacheTtl is null"); | ||
|
||
this.caseInsensitiveNameMatching = caseInsensitiveNameMatching; | ||
this.jdbcTypesMappedToVarchar = jdbcTypesMappedToVarchar; | ||
this.jdbcTypesMappedToVarchar = ImmutableSet.copyOf(requireNonNull(jdbcTypesMappedToVarchar, "jdbcTypesMappedToVarchar is null")); |
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 move this up, after this.connectionFactory =
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.
Sorry, missed that one ...
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.
Fixed
|
||
protected Optional<ColumnMapping> getForcedMappingToVarchar(JdbcTypeHandle typeHandle) | ||
{ | ||
if (jdbcTypesMappedToVarchar.contains(typeHandle.getJdbcTypeName().get())) { |
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 (typeHandle.getJdbcTypeName().isPresent() && jdbcTypesMappedToVarchar.contains(typeHandle.getJdbcTypeName().get()))
presto-base-jdbc/src/test/java/io/prestosql/plugin/jdbc/TestBaseJdbcConfig.java
Show resolved
Hide resolved
35644d3
to
21bae0e
Compare
21bae0e
to
50276f2
Compare
Merged as 52c7c39, thanks! I fixed an unused import and introduced |
Add optional catalog parameters that map Jdbc types to varchar:
jdbc-types-mapped-to-varchar = jdbcTypeName[,jdbcTypeName[,...]]
Now catalogs can control whether or not to fetch unsupported Presto types and to stay compatible when future support will be implemented.
For example:
PostgreSQL catalog with the following configuration will map
tsrange
andinet
to Presto VARCHAR:jdbc-types-mapped-to-varchar = tsrange,inet
Ref prestodb/presto#11833