Skip to content

[CALCITE-6022] Support "CREATE TABLE LIKE" DDL#3442

Merged
JiajunBernoulli merged 1 commit intoapache:mainfrom
macroguo-ghy:6022-like
Oct 19, 2023
Merged

[CALCITE-6022] Support "CREATE TABLE LIKE" DDL#3442
JiajunBernoulli merged 1 commit intoapache:mainfrom
macroguo-ghy:6022-like

Conversation

@macroguo-ghy
Copy link
Contributor

No description provided.

import java.util.stream.Collectors;

/**
* Parse tree for {@code CREATE TABLE LIKE} statement.
Copy link
Contributor

Choose a reason for hiding this comment

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

It is better to give a CREATE TABLE LIKE sql example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for your suggestion. But I haven't seen other DDL SqlNode contains any examples. And I think user can aware of how to use CREATE TABLE LIKE syntax by referring to reference.md.

Copy link
Contributor

Choose a reason for hiding this comment

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

Get it.

.collect(Collectors.toSet());
}

@Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
Copy link
Contributor

@LakeShen LakeShen Sep 28, 2023

Choose a reason for hiding this comment

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

Could we add the sql dialect transform unit test for SqlCreateTableLike?

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 think in Calcite, all DDL in calcite-server will be execute by calcite instead of executing in other adapter(you can refer to org.apache.calcite.prepare.CalcitePrepareImpl#prepare2_).
So in THIS jira, we don't need to care about if the DDL command can execute in other dbms. Maybe we can log a new jira to discuss "Dialect for DDL".

Copy link
Contributor

Choose a reason for hiding this comment

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

Get it

return Pair.of(schema, name);
}

static Table table(CalcitePrepare.Context context, SqlIdentifier id) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we give some code comments for this method?It is better to help others understand this 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.

Fixed.

@LakeShen
Copy link
Contributor

@macroguo-ghy ,thank you for opening this PR, left a couple of comments!

Copy link
Contributor Author

@macroguo-ghy macroguo-ghy left a comment

Choose a reason for hiding this comment

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

Hi @LakeShen @JiajunBernoulli, thanks for your review and suggestion. I reply to your comment. Please help me review again if you have time.

import java.util.stream.Collectors;

/**
* Parse tree for {@code CREATE TABLE LIKE} statement.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for your suggestion. But I haven't seen other DDL SqlNode contains any examples. And I think user can aware of how to use CREATE TABLE LIKE syntax by referring to reference.md.

.collect(Collectors.toSet());
}

@Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
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 think in Calcite, all DDL in calcite-server will be execute by calcite instead of executing in other adapter(you can refer to org.apache.calcite.prepare.CalcitePrepareImpl#prepare2_).
So in THIS jira, we don't need to care about if the DDL command can execute in other dbms. Maybe we can log a new jira to discuss "Dialect for DDL".

return Pair.of(schema, name);
}

static Table table(CalcitePrepare.Context context, SqlIdentifier id) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

)
}

SqlCreate SqlCreateTableLike(Span s, boolean replace, boolean ifNotExists, SqlIdentifier id) :
Copy link
Contributor

Choose a reason for hiding this comment

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

You calling SqlCreateTableLike by SqlCreateTable .

SqlCreateTable is added to createStatementParserMethods

Can we add SqlCreateTableLike to createStatementParserMethods?

Copy link
Contributor Author

@macroguo-ghy macroguo-ghy Oct 8, 2023

Choose a reason for hiding this comment

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

Fix this. Could you please review this PR again? @JiajunBernoulli

(
<#-- additional literal parser methods are included here -->
<#list (parser.createStatementParserMethods!default.parser.createStatementParserMethods) as method>
<#if method = "SqlCreateTableLike">
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, this makes things too complicated.

Can we add it in createStatementParserMethods?
image

Copy link
Contributor Author

@macroguo-ghy macroguo-ghy Oct 9, 2023

Choose a reason for hiding this comment

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

I'm afraid not, we need to use LOOKAHEAD to distinguish CREATE TABLE and CREATE TABLE ... LIKE.
create = ${method}(s, replace), in this line , ${method} will be replaced by createStatementParserMethod, so we can not use LOOKAHEAD(...) SqlCreateTableLike replace SqlCreateTableLike. This will result in compilation errors.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, I misled you.

Please drop the last commit(Add SqlCreateTableLike to createStatementParserMethods).
image

I will merge it at the weekends.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I reverted and squashed the commits.

@macroguo-ghy
Copy link
Contributor Author

Hi @JiajunBernoulli, can you review this PR again? I believe we can merge it before 1.36.0 release.

*/
public class SqlCreateTableLike extends SqlCreate {
private static final SqlOperator OPERATOR =
new SqlSpecialOperator("CREATE TABLE LIKE", SqlKind.CREATE_TABLE);
Copy link
Contributor

Choose a reason for hiding this comment

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

We need SqlKind.CREATE_TABLE_LIKE because SqlCreateTableLike not extends SqlCreateTable.

User maybe mistake if them are both SqlKind.CREATE_TABLE.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

}

/** Return the table from the given {@code} context and {@code} name. */
static Table table(CalcitePrepare.Context context, SqlIdentifier name) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Used only once.

It doesn't seem necessary to abstract it as a 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.

Deleted.

final boolean includingDefaults =
optionSet.contains(SqlCreateTableLike.LikeOption.DEFAULTS)
|| optionSet.contains(SqlCreateTableLike.LikeOption.ALL);
ief = new NullInitializerExpressionFactory() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Need class name and document, not anonymous 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.

Fixed.

}
}

@Test void testCreateTableLike() throws Exception {
Copy link
Contributor

Choose a reason for hiding this comment

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

Need one JIRA link and document.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

}

try {
x = s.executeUpdate("insert into t2 values (3, 4, 5, 6)");
Copy link
Contributor

Choose a reason for hiding this comment

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

We can use assertThrows.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

try {
x = s.executeUpdate("insert into t2 values (3, 4, 5)");
fail("expected error, got " + x);
} catch (SQLException e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

assertThrows

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

assertThat(r.getInt("H"), is(3));
assertThat(r.wasNull(), is(false));
assertThat(r.getInt("I"), is(4));
assertThat(r.getInt("J"), is(0)); // excluding generated column
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is 0, not null?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because java.sql.ResultSet#getInt(java.lang.String) will return 0 if the value is SQL NULL. I add assertThat(r.wasNull(), is(true)) to clarify.

Copy link
Contributor Author

@macroguo-ghy macroguo-ghy left a comment

Choose a reason for hiding this comment

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

Thanks for your reviews, @JiajunBernoulli ! I have pushed a new commit, and I noticed that Julian updating the lint rule, so I have made a git rebase.

assertThat(r.getInt("H"), is(3));
assertThat(r.wasNull(), is(false));
assertThat(r.getInt("I"), is(4));
assertThat(r.getInt("J"), is(0)); // excluding generated column
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because java.sql.ResultSet#getInt(java.lang.String) will return 0 if the value is SQL NULL. I add assertThat(r.wasNull(), is(true)) to clarify.

final boolean includingDefaults =
optionSet.contains(SqlCreateTableLike.LikeOption.DEFAULTS)
|| optionSet.contains(SqlCreateTableLike.LikeOption.ALL);
ief = new NullInitializerExpressionFactory() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

}
}

@Test void testCreateTableLike() throws Exception {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

}

try {
x = s.executeUpdate("insert into t2 values (3, 4, 5, 6)");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

try {
x = s.executeUpdate("insert into t2 values (3, 4, 5)");
fail("expected error, got " + x);
} catch (SQLException e) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

*/
public class SqlCreateTableLike extends SqlCreate {
private static final SqlOperator OPERATOR =
new SqlSpecialOperator("CREATE TABLE LIKE", SqlKind.CREATE_TABLE);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

}

/** Return the table from the given {@code} context and {@code} name. */
static Table table(CalcitePrepare.Context context, SqlIdentifier name) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Deleted.

}
}

if (pair.left.plus().getTable(pair.right) != null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Check can be first, we can moved them to line 568.
And then add one line comment to introduce InitializerExpressionFactory.

public void execute(SqlCreateTableLike create,
CalcitePrepare.Context context) {
final Pair<CalciteSchema, String> pair = schema(context, true, create.name);
final JavaTypeFactory typeFactory = context.getTypeFactory();
Copy link
Contributor

Choose a reason for hiding this comment

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

typeFactory and rowType can be moved to last because them are used by last code.

@JiajunBernoulli
Copy link
Contributor

PR is already good, and the little suggestion can be made when you squash commits.

@macroguo-ghy
Copy link
Contributor Author

OK, I have squashed the commits. Thanks for your reviews! @LakeShen @JiajunBernoulli

@JiajunBernoulli JiajunBernoulli added the LGTM-will-merge-soon Overall PR looks OK. Only minor things left. label Oct 16, 2023
@JiajunBernoulli
Copy link
Contributor

@macroguo-ghy , Commit message should same as JIRA summary.

Support "CREATE TABLE ... LIKE" DDL in server module

@macroguo-ghy
Copy link
Contributor Author

Sorry, my mistake. I have edited the commit message. @JiajunBernoulli

@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 1 Code Smell

83.4% 83.4% Coverage
0.0% 0.0% Duplication

@JiajunBernoulli JiajunBernoulli merged commit 23b7931 into apache:main Oct 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

LGTM-will-merge-soon Overall PR looks OK. Only minor things left.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants