-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Support alibaba cloud tablestore #16151
Support alibaba cloud tablestore #16151
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.
Sorry for my delay. Really appreciate your contribution! Just a few coding style issues. (I might more focus on the coding style in the first round review. ).
This is really a big one, I will continue the review by the end of this week. Again, thank you for the contribution! Feel free to ping me via slack or reply the comments here if you have any questions or concern.
presto-tablestore/pom.xml
Outdated
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> |
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.
indentation style looks not following other sections
{ | ||
enum Type | ||
{ | ||
auto, |
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 we prefer using upper case for enum
.collect(Collectors.toSet()); | ||
return IndexFirstSet.custom(tables); | ||
} | ||
String str = "use hint like these: " + |
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.
thinking if we could extract 'str' as an constant
can we have a meaningful name rather than 'str'?
private static SchemaTableName checkAndAssemblySchemaTableName(Optional<String> currentConnectionSchema, | ||
String hintKey, | ||
String unit) | ||
throws IllegalArgumentException |
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.
hmmm, why we need explicitly throws a runtime exception in a private method?
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 mean the exception should be throw in a public method?
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.
Not really, I'm just curious
- Why we need a "throws" for a RuntimeException? We don't have to, am I right? (IllegalArgumentException is a runtime/unchecked exception, isn't it?)
- In case you just want to use 'throws' to make a strong contract to the caller, but 'checkAndAssemblySchemaTableName' is a private method. I cannot see the benefits of the 'throws' here.
|
||
public static Field findField(Class<?> clazz, String name, Class<?> type) | ||
{ | ||
checkArgument(clazz != null, "Class must not be 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.
we might prefer to use requireNonNull instead of checkArgument here
long delta = System.nanoTime() - t1; | ||
|
||
if (delta >= 10 * 1_000_000) { | ||
log.debug("split scan new fetch, queryId=%s currentRows=%s deltaApiCost=%sms", queryId, rows, delta / 1000_1000.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.
why 1000_1000.0 ?
next(); //有可能报错 | ||
long delta = System.nanoTime() - t1; | ||
|
||
if (delta >= 10 * 1_000_000) { |
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.
Why we have 10 times 1_000_000? should we have a constant here?
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.
- added a constant.
- It is to make sure we only log every 10ms -- so it will not generate too much logs.
public class TablestoreConnector | ||
implements Connector | ||
{ | ||
private static final Logger LOG = Logger.get(TablestoreConnector.class); |
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 might prefer using lower case 'log'
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
catch (Exception e) { | ||
type = "others_error"; | ||
cause = e; | ||
invalidate = true; //有可能客户端被关闭之类的情况 |
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.
What happens if the client has been shutdown?
What's 'invalidate' for? I couldn't find any usage in this class.
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.
Indeed not needed, will delete it.
else { | ||
x = querySplitsFromSearchIndex(session, th, constraint, tupleDomainStr, matchedSearchIndexes); | ||
t1 = currentTimeMillis() - t1; | ||
log.info("getSplits() end, found %s indexes, query=%s splitsSize=%s apiCost=%sms.", |
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.
Will this generate too many logs?
If the splits size and t1 are important can we expose them by jmx?
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 only generate one log per query.
|
||
public TablestoreConnectorFactory(String name, ClassLoader classLoader) | ||
{ | ||
checkArgument(!isNullOrEmpty(name), "name is null or 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.
Using requireNonNull
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
} | ||
|
||
/** | ||
* 查看总行数的查询 |
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 this comment is not needed. The name of this method explains the purpose well.
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
Iterator<Queue<Split>> i = ss.iterator(); | ||
while (i.hasNext()) { | ||
Queue<Split> x = i.next(); | ||
Split e = x.poll(); //移除元素 |
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.
comment not needed
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
newList.add(e); | ||
} | ||
else { | ||
i.remove(); //移除队列 |
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.
comment not needed
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
@Override | ||
protected void next() | ||
{ | ||
rowIterator.next(); //有可能报错 |
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.
remove the comment. we can add a try/catch if you think the exception should be handled here.
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
@Override | ||
protected void next() | ||
{ | ||
current = rowIterator.next(); //有可能报错 |
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.
comment not needed
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
switch (target.getType()) { | ||
case INTEGER: | ||
long v1 = target.asLong(); | ||
if (v1 == Long.MAX_VALUE) { |
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.
static import Long.MAX_VALUE
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
{ | ||
if (value == null) { | ||
String str = format("We need a nonnull instance of type[%s], but it's null.", target.getSimpleName()); | ||
throw new NullPointerException(str); |
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.
Using requireNonNull?
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
static final String COLUMN_NAME_2 = "test_column2"; | ||
static final String COLUMN_NAME_3 = "test_column3"; | ||
|
||
static final String PK_1_int = "pk1_int"; |
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.
All upper case for a constant
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
import static java.util.Locale.ENGLISH; | ||
import static java.util.Objects.requireNonNull; | ||
|
||
public class TestingConnectorSession |
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 there has been a TestingConnectorSession in com.facebook.presto.testing, do we really need to create a new 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.
Removed tablestore's TestingConnectorSession and reuse presto-main's TestingConnectorSession
@beinan Thanks for the review, I will make the changes accordingly this week. |
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.
@xumingming Nice work! Just added a few comments.
BTW, could you create a doc for this new connector?
protected abstract void next(); | ||
|
||
/** | ||
* 为了出错时好定位问题行 |
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.
Noticed that there're a few other comments in Chinese. Could you remove them or translate them into English?
public long getReadTimeNanos() | ||
{ | ||
checkClosed(); | ||
return (currentTimeMillis() - startTimestamp) * 1000_000; |
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.
The value of 1000_000
is used multiple times in this file. May we refactor it into a constant variable?
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
return injector.getInstance(TablestoreConnector.class); | ||
} | ||
catch (Exception e) { | ||
throw Throwables.propagate(e); |
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.
nit: What about just throwing an exception here? A quick search of the Presto codebase shows that we don't use Throwables.propagate
.
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
public class TablestoreRecordSetProvider | ||
implements ConnectorRecordSetProvider | ||
{ | ||
private static final Logger LOG = Logger.get(TablestoreRecordSetProvider.class); |
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.
May we use the lower case of LOG
here?
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
public class TablestoreRecordSink | ||
implements RecordSink | ||
{ | ||
private static final Logger LOG = Logger.get(TablestoreRecordSink.class); |
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.
Same here. May we use log
?
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
presto-tablestore/pom.xml
Outdated
</ignoredDependencies> | ||
</configuration> | ||
</plugin> | ||
</plugins> |
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.
indentation looks not correct.
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
|
||
import java.util.concurrent.TimeUnit; | ||
|
||
public class CustomRetryStrategy |
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.
shall we have more meaningful name here? your call
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.
how about timeoutRetryStrategy?
static IndexFirstSet custom(@Nonnull Set<SchemaTableName> tables) | ||
{ | ||
if (tables.size() == 0) { | ||
return none(); |
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.
why not just return NONE? any benefits to use a separate method none()?
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.
seems only be consist with cutom() method, so all place will use these methods rather than direct referencing these fields.
String x = String.valueOf(value); | ||
String str = "convert() failed for " + (toPrimaryKeyNotColumnValue ? "PrimaryKeyValue" : "ColumnValue") + | ||
", required type is " + type + ", and type of value is " + value.getClass() + ", and value="; | ||
log.error(str + x, e); //全部打印出来 |
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.
remove the comments
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
} | ||
catch (Throwable e) { | ||
String x = String.valueOf(value); | ||
String str = "convert() failed for " + (toPrimaryKeyNotColumnValue ? "PrimaryKeyValue" : "ColumnValue") + |
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.
is it better to use String.format? your call
Also we might need a more meaningful name instead of str
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
if (x.length() > 20) { | ||
y = x.substring(0, 20) + "......"; | ||
} | ||
throw new IllegalArgumentException(str + y, e); //打印部分 |
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.
remove the comment
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
acceptedTypes = new Class[] {String.class, byte[].class, Slice.class}; | ||
} | ||
} | ||
catch (Throwable e) { |
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.
Should we handle all the throwable here? I think most of Errors should not handled by application code. What do you think?
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.
Agree with you. Changed to Exception
|
||
String y = x; | ||
if (x.length() > 20) { | ||
y = x.substring(0, 20) + "......"; |
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.
nit: to be consistent, is it better to use triple dot "..."?
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
String v2 = target.asString(); | ||
return PrimaryKeyValue.fromString(v2 + "\0"); | ||
case BINARY: | ||
byte[] v3 = target.asBinary(); |
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 don't think v1, v2 and v3 are very meaningful name here.
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 agree with you, changed it.
Good call, doc is a new requirement to commit guideline https://lists.prestodb.io/g/presto-tsc/topic/adding_doc_requirement_to/81082141?p=,,,20,0,0,0::recentpostdate/sticky,,,20,2,0,81082141 |
I am back, and will make the necessary changes :) |
328d87c
to
8f544a3
Compare
I have made changes according to your comments, can you help to do another round of review @beinan @ChunxuTang |
Added the documentation. |
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.
@xumingming Thanks for your huge work! Generally looks good to me. Just left some minor suggestions in the code. @beinan Could you also have another round of review?
BTW, I noticed that there are quite a number of commits in this PR and most of them are just for fixing comments or updating versions. @xumingming When you complete changes, could you merge them into one commit? Thanks~
private int clientRetrySeconds = 120; | ||
private int connectTimeoutSeconds = 10; | ||
private int socketTimeoutSeconds = 50; | ||
private int syncClientWaitTimeoutSeconds = 60; |
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.
Are these settings configurable by users? If yes, could you add documentation of these settings in the alibaba cloud tablestore doc?
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, they are configurable, but I'd prefer merge this first PR into prestodb first, and later I can expose more settings for user to tune.
.indexName(indexName) | ||
.scanQuery(ScanQuery.newBuilder() | ||
.query(buildQueryForCurrentConditions(tupleDomain)) | ||
.limit(2000) |
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.
Just curious why the value here is 2000. Is it from the empirical experience?
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 recommended by the tablestore team, it is not limiting the result count to 2000, it is limiting to only return 2000 for every request.
List<SchemaTableName> list = listTables(session, prefix.getSchemaName()); | ||
for (SchemaTableName stn : list) { | ||
String qtn = prefix.getTableName(); | ||
if (qtn != null && !qtn.equalsIgnoreCase(stn.getTableName())) { //如果tableName==null,就匹配全部;否则按tableName过滤 |
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.
Could you remove the comment or translate it into English?
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
|
||
private static ClassLoader getClassLoader() | ||
{ | ||
ClassLoader tcl = Thread.currentThread().getContextClassLoader(); //PrestoServer对应启动线程的类加载器 |
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.
Could you remove the comment?
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
return "TablestoreTransactionHandle{" + | ||
"uuid=" + uuid + | ||
'}'; |
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.
Looks that this is not that wide to split into 3 lines. But either way works for me. Your call.
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
} | ||
|
||
/** | ||
* 类似于:0:(min,0) 1:(0,1) 2:(1,2) 3:(2,3) 4:(3,4) 5:(4,5) 6:(5,6) 7:(6,7) 8:(7,8) 9:(8,max),第一个是分区,第二个是min,第三个是max |
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 the comment here is necessary, could you translate it into English?
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
List<Split> rList = divideAndMergeAndShuffle(4, list); | ||
assertEquals("0:(min,3) 1:(3,5) 2:(5,7) 2:(7,max)", print(rList)); | ||
|
||
//希望合并到3份,但也只能合并到4份,因为有些合并不了了 |
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.
Maybe remove the comment here? I guess no matter we merge them to 3 or 4, it won't influence the major features.
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
long n2 = System.currentTimeMillis(); | ||
|
||
assertEquals(10000, rList.size()); | ||
System.out.println("测试性能-" + i + ": " + (n2 - n1) + "ms"); |
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.
Maybe change the words to English?
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
|
||
ConnectorSession cs = session(); | ||
int x = getQueryVersion(cs); | ||
assertEquals(2, x); //默认不开启 |
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.
Maybe remove the comment?
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
|
||
TestingConnectorSession cs = session(); | ||
boolean x = enablePartitionPruning(cs); | ||
assertTrue(x); //默认开启 |
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.
Same as above.
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
39071a7
to
f88c0f8
Compare
@ChunxuTang updated the code according to all the comments, and merged all the relative commits into one commit. |
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.
@ChunxuTang @zhenxiao do you two wanna take a second look? otherwise I will merge this PR
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!
Let's merge it? |
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 work, @xumingming
some minor coding style issues
presto-tablestore/src/main/java/com/facebook/presto/tablestore/TablestoreFacade.java
Outdated
Show resolved
Hide resolved
presto-tablestore/src/main/java/com/facebook/presto/tablestore/TablestoreFacade.java
Outdated
Show resolved
Hide resolved
presto-tablestore/src/main/java/com/facebook/presto/tablestore/TablestoreFacade.java
Outdated
Show resolved
Hide resolved
presto-tablestore/src/main/java/com/facebook/presto/tablestore/TablestoreFacade.java
Outdated
Show resolved
Hide resolved
presto-tablestore/src/main/java/com/facebook/presto/tablestore/TablestoreFacade.java
Outdated
Show resolved
Hide resolved
@zhenxiao For the |
8b58891
to
1ec7804
Compare
@zhenxiao Any further comments? |
1ec7804
to
72cfc23
Compare
@zhenxiao Any further comments? |
1 similar comment
@zhenxiao Any further comments? |
@beinan @zhenxiao @ChunxuTang Any further comments? |
@zhenxiao Any further comments? |
@zhenxiao Any comments? |
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.
thanks, @xumingming
a few more comments
presto-tablestore/src/main/java/com/facebook/presto/tablestore/IndexSelectionStrategy.java
Outdated
Show resolved
Hide resolved
} | ||
searchType = searchType.getSuperclass(); | ||
} | ||
return 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.
+1. let's make it Optional, instead of returning null
presto-tablestore/src/main/java/com/facebook/presto/tablestore/ReflectionUtils.java
Outdated
Show resolved
Hide resolved
presto-tablestore/src/main/java/com/facebook/presto/tablestore/ReflectionUtils.java
Outdated
Show resolved
Hide resolved
presto-tablestore/src/main/java/com/facebook/presto/tablestore/ReflectionUtils.java
Outdated
Show resolved
Hide resolved
72cfc23
to
3a1a676
Compare
@zhenxiao all comments resolved, can you help review again? |
@beinan @zhenxiao @ChunxuTang Any chance to boost the PR review process a little bit? It has already taken 3 months, quite frustrating. |
Test plan - (Please fill in how you tested your changes)
Tested on my desktop with real config.