Skip to content
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

Closed

Conversation

xumingming
Copy link
Contributor

Test plan - (Please fill in how you tested your changes)

Tested on my desktop with real config.

== RELEASE NOTES ==

General Changes

*  Add a new connector: tablestore for Alibaba Cloud's Tablestore service

@rohanpednekar rohanpednekar requested a review from beinan May 27, 2021 00:26
Copy link
Member

@beinan beinan left a 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.

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Copy link
Member

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,
Copy link
Member

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: " +
Copy link
Member

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
Copy link
Member

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?

Copy link
Contributor Author

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?

Copy link
Member

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

  1. 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?)
  2. 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");
Copy link
Member

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);
Copy link
Member

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) {
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. added a constant.
  2. 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);
Copy link
Member

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'

Copy link
Contributor Author

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; //有可能客户端被关闭之类的情况
Copy link
Member

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.

Copy link
Contributor Author

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.",
Copy link
Member

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?

Copy link
Contributor Author

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");
Copy link
Member

Choose a reason for hiding this comment

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

Using requireNonNull

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

}

/**
* 查看总行数的查询
Copy link
Member

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.

Copy link
Contributor Author

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(); //移除元素
Copy link
Member

Choose a reason for hiding this comment

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

comment not needed

Copy link
Contributor Author

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(); //移除队列
Copy link
Member

Choose a reason for hiding this comment

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

comment not needed

Copy link
Contributor Author

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(); //有可能报错
Copy link
Member

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.

Copy link
Contributor Author

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(); //有可能报错
Copy link
Member

Choose a reason for hiding this comment

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

comment not needed

Copy link
Contributor Author

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) {
Copy link
Member

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

Copy link
Contributor Author

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);
Copy link
Member

Choose a reason for hiding this comment

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

Using requireNonNull?

Copy link
Contributor Author

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";
Copy link
Member

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

Copy link
Contributor Author

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
Copy link
Member

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?

Copy link
Contributor Author

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

@xumingming
Copy link
Contributor Author

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.

@beinan Thanks for the review, I will make the changes accordingly this week.

Copy link
Member

@ChunxuTang ChunxuTang left a 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();

/**
* 为了出错时好定位问题行
Copy link
Member

@ChunxuTang ChunxuTang Jun 2, 2021

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;
Copy link
Member

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?

Copy link
Contributor Author

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);
Copy link
Member

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.

Copy link
Contributor Author

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);
Copy link
Member

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?

Copy link
Contributor Author

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);
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

</ignoredDependencies>
</configuration>
</plugin>
</plugins>
Copy link
Member

Choose a reason for hiding this comment

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

indentation looks not correct.

Copy link
Contributor Author

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
Copy link
Member

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

Copy link
Collaborator

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();
Copy link
Member

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()?

Copy link
Contributor Author

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); //全部打印出来
Copy link
Member

Choose a reason for hiding this comment

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

remove the comments

Copy link
Contributor Author

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") +
Copy link
Member

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

Copy link
Contributor Author

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); //打印部分
Copy link
Member

Choose a reason for hiding this comment

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

remove the comment

Copy link
Contributor Author

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) {
Copy link
Member

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?

Copy link
Contributor Author

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) + "......";
Copy link
Member

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 "..."?

Copy link
Contributor Author

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();
Copy link
Member

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.

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 agree with you, changed it.

@beinan
Copy link
Member

beinan commented Jun 4, 2021

@xumingming Nice work! Just added a few comments.
BTW, could you create a doc for this new connector?

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

@xumingming
Copy link
Contributor Author

I am back, and will make the necessary changes :)

@xumingming xumingming force-pushed the support-alibaba-cloud-tablestore branch from 328d87c to 8f544a3 Compare June 27, 2021 12:23
@xumingming
Copy link
Contributor Author

I have made changes according to your comments, can you help to do another round of review @beinan @ChunxuTang

@xumingming
Copy link
Contributor Author

@xumingming Nice work! Just added a few comments.
BTW, could you create a doc for this new connector?

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

Added the documentation.

Copy link
Member

@ChunxuTang ChunxuTang left a 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~

Comment on lines +24 to +27
private int clientRetrySeconds = 120;
private int connectTimeoutSeconds = 10;
private int socketTimeoutSeconds = 50;
private int syncClientWaitTimeoutSeconds = 60;
Copy link
Member

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?

Copy link
Contributor Author

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)
Copy link
Member

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?

Copy link
Contributor Author

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过滤
Copy link
Member

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?

Copy link
Contributor Author

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对应启动线程的类加载器
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 69 to 71
return "TablestoreTransactionHandle{" +
"uuid=" + uuid +
'}';
Copy link
Member

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.

Copy link
Contributor Author

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
Copy link
Member

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?

Copy link
Contributor Author

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份,因为有些合并不了了
Copy link
Member

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.

Copy link
Contributor Author

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");
Copy link
Member

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?

Copy link
Contributor Author

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); //默认不开启
Copy link
Member

Choose a reason for hiding this comment

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

Maybe remove the comment?

Copy link
Contributor Author

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); //默认开启
Copy link
Member

Choose a reason for hiding this comment

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

Same as above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@xumingming xumingming force-pushed the support-alibaba-cloud-tablestore branch 3 times, most recently from 39071a7 to f88c0f8 Compare July 8, 2021 02:45
@xumingming
Copy link
Contributor Author

@ChunxuTang updated the code according to all the comments, and merged all the relative commits into one commit.

@xumingming xumingming requested a review from beinan July 8, 2021 04:58
Copy link
Member

@beinan beinan left a 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

Copy link
Member

@ChunxuTang ChunxuTang left a comment

Choose a reason for hiding this comment

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

LGTM!

@xumingming
Copy link
Contributor Author

Let's merge it?

Copy link
Collaborator

@zhenxiao zhenxiao left a 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

@xumingming
Copy link
Contributor Author

@zhenxiao For the return null in RowSearchIterator4CountStar.java, it can return null because the returned value will not be used, it is an optimization for count(*).

@xumingming xumingming requested a review from zhenxiao July 13, 2021 07:20
@xumingming xumingming force-pushed the support-alibaba-cloud-tablestore branch from 8b58891 to 1ec7804 Compare July 13, 2021 07:26
@xumingming
Copy link
Contributor Author

@zhenxiao Any further comments?

@xumingming xumingming force-pushed the support-alibaba-cloud-tablestore branch from 1ec7804 to 72cfc23 Compare July 22, 2021 04:47
@xumingming
Copy link
Contributor Author

@zhenxiao Any further comments?

1 similar comment
@xumingming
Copy link
Contributor Author

@zhenxiao Any further comments?

@xumingming
Copy link
Contributor Author

@beinan @zhenxiao @ChunxuTang Any further comments?

@xumingming
Copy link
Contributor Author

@zhenxiao Any further comments?

@xumingming
Copy link
Contributor Author

@zhenxiao Any comments?

Copy link
Collaborator

@zhenxiao zhenxiao left a 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-docs/src/main/sphinx/connector/tablestore.rst Outdated Show resolved Hide resolved
presto-docs/src/main/sphinx/connector/tablestore.rst Outdated Show resolved Hide resolved
presto-docs/src/main/sphinx/connector/tablestore.rst Outdated Show resolved Hide resolved
presto-docs/src/main/sphinx/connector/tablestore.rst Outdated Show resolved Hide resolved
}
searchType = searchType.getSuperclass();
}
return null;
Copy link
Collaborator

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

@xumingming xumingming force-pushed the support-alibaba-cloud-tablestore branch from 72cfc23 to 3a1a676 Compare August 9, 2021 07:57
@xumingming
Copy link
Contributor Author

@zhenxiao all comments resolved, can you help review again?

@xumingming xumingming requested a review from zhenxiao August 11, 2021 08:13
@xumingming
Copy link
Contributor Author

@beinan @zhenxiao @ChunxuTang Any chance to boost the PR review process a little bit? It has already taken 3 months, quite frustrating.

@xumingming xumingming closed this Nov 29, 2021
@xumingming xumingming deleted the support-alibaba-cloud-tablestore branch November 29, 2021 11:58
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.

4 participants