diff --git a/core/src/main/java/org/apache/calcite/sql/SqlCollation.java b/core/src/main/java/org/apache/calcite/sql/SqlCollation.java index b02035f79109..5f6e4805f764 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlCollation.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlCollation.java @@ -17,8 +17,10 @@ package org.apache.calcite.sql; import org.apache.calcite.config.CalciteSystemProperty; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.parser.SqlParserUtil; import org.apache.calcite.util.Glossary; +import org.apache.calcite.util.ImmutableNullableList; import org.apache.calcite.util.SerializableCharset; import org.apache.calcite.util.Util; @@ -37,6 +39,8 @@ import static org.apache.calcite.util.Static.RESOURCE; +import static java.util.Objects.requireNonNull; + /** * A SqlCollation is an object representing a Collate * statement. It is immutable. @@ -113,6 +117,25 @@ public SqlCollation( this.collationName = generateCollationName(charset); } + /** Encode all the information require to reconstruct a SqlCollection in a SqlList object. */ + public SqlNodeList asList() { + return new SqlNodeList( + ImmutableNullableList.of( + SqlLiteral.createCharString(this.getCollationName(), SqlParserPos.ZERO), + SqlLiteral.createSymbol(coercibility, SqlParserPos.ZERO)), + SqlParserPos.ZERO); + } + + /** The inverse of the {@link #asList} function. */ + public static SqlCollation fromSqlList(SqlNodeList list) { + assert list.size() == 2; + String name = ((SqlLiteral) list.get(0)).getValueAs(String.class); + Coercibility coercibility = ((SqlLiteral) list.get(1)).symbolValue(Coercibility.class); + return new SqlCollation( + name, + requireNonNull(coercibility, "coercibility")); + } + /** * Creates a Collation by its coercibility, locale, charset and strength. */ diff --git a/core/src/main/java/org/apache/calcite/sql/SqlLambda.java b/core/src/main/java/org/apache/calcite/sql/SqlLambda.java index c0f8b2b145e6..696753b4f4e5 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlLambda.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlLambda.java @@ -107,6 +107,13 @@ private static class SqlLambdaOperator extends SqlSpecialOperator { super("->", SqlKind.LAMBDA); } + @Override public SqlCall createCall( + @Nullable SqlLiteral functionQualifier, SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlLambda(pos, + (SqlNodeList) requireNonNull(operands[0], "parameters"), + requireNonNull(operands[1], "expression")); + } + @Override public RelDataType deriveType( SqlValidator validator, SqlValidatorScope scope, SqlCall call) { final SqlLambda lambdaExpr = (SqlLambda) call; diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlAttributeDefinition.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlAttributeDefinition.java index a25528784608..494c262959a0 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlAttributeDefinition.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlAttributeDefinition.java @@ -21,25 +21,37 @@ import org.apache.calcite.sql.SqlDataTypeSpec; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; import org.apache.calcite.sql.SqlWriter; import org.apache.calcite.sql.parser.SqlParserPos; - -import com.google.common.collect.ImmutableList; +import org.apache.calcite.util.ImmutableNullableList; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; +import static java.util.Objects.requireNonNull; + /** * Parse tree for SqlAttributeDefinition, * which is part of a {@link SqlCreateType}. */ public class SqlAttributeDefinition extends SqlCall { - private static final SqlSpecialOperator OPERATOR = - new SqlSpecialOperator("ATTRIBUTE_DEF", SqlKind.ATTRIBUTE_DEF); + private static final SqlOperator OPERATOR = + new SqlSpecialOperator("ATTRIBUTE_DEF", SqlKind.ATTRIBUTE_DEF) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlAttributeDefinition(pos, + (SqlIdentifier) requireNonNull(operands[0], "name"), + (SqlDataTypeSpec) requireNonNull(operands[1], "dataType"), + operands[2], + operands[3] != null ? SqlCollation.fromSqlList((SqlNodeList) operands[3]) : null); + } + }; public final SqlIdentifier name; public final SqlDataTypeSpec dataType; @@ -60,8 +72,10 @@ public class SqlAttributeDefinition extends SqlCall { return OPERATOR; } + @SuppressWarnings("nullness") @Override public List getOperandList() { - return ImmutableList.of(name, dataType); + return ImmutableNullableList.of(name, dataType, expression, + collation != null ? collation.asList() : null); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCheckConstraint.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCheckConstraint.java index a74ed3e90ef7..8106f2d1e81c 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCheckConstraint.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCheckConstraint.java @@ -19,6 +19,7 @@ import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; @@ -30,14 +31,23 @@ import java.util.List; +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code UNIQUE}, {@code PRIMARY KEY} constraints. * *

And {@code FOREIGN KEY}, when we support it. */ public class SqlCheckConstraint extends SqlCall { - private static final SqlSpecialOperator OPERATOR = - new SqlSpecialOperator("CHECK", SqlKind.CHECK); + private static final SqlOperator OPERATOR = + new SqlSpecialOperator("CHECK", SqlKind.CHECK) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlCheckConstraint(pos, + (SqlIdentifier) operands[0], + requireNonNull(operands[1], "expression")); + } + }; private final @Nullable SqlIdentifier name; private final SqlNode expression; diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlColumnDeclaration.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlColumnDeclaration.java index e37075f63123..d57fcb502b2b 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlColumnDeclaration.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlColumnDeclaration.java @@ -21,36 +21,50 @@ import org.apache.calcite.sql.SqlDataTypeSpec; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; import org.apache.calcite.sql.SqlWriter; import org.apache.calcite.sql.parser.SqlParserPos; - -import com.google.common.collect.ImmutableList; +import org.apache.calcite.util.ImmutableNullableList; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code UNIQUE}, {@code PRIMARY KEY} constraints. * *

And {@code FOREIGN KEY}, when we support it. */ public class SqlColumnDeclaration extends SqlCall { - private static final SqlSpecialOperator OPERATOR = - new SqlSpecialOperator("COLUMN_DECL", SqlKind.COLUMN_DECL); + private static final SqlOperator OPERATOR = + new SqlSpecialOperator("COLUMN_DECL", SqlKind.COLUMN_DECL) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlColumnDeclaration(pos, + (SqlIdentifier) requireNonNull(operands[0], "name"), + (SqlDataTypeSpec) requireNonNull(operands[1], "dataType"), + operands[2], + operands[3] != null + ? ColumnStrategy.valueOf(((SqlIdentifier) operands[3]).getSimple()) + : null); + } + }; public final SqlIdentifier name; public final SqlDataTypeSpec dataType; public final @Nullable SqlNode expression; - public final ColumnStrategy strategy; + // The Babel parser can supply null for the strategy + public final @Nullable ColumnStrategy strategy; /** Creates a SqlColumnDeclaration; use {@link SqlDdlNodes#column}. */ SqlColumnDeclaration(SqlParserPos pos, SqlIdentifier name, SqlDataTypeSpec dataType, @Nullable SqlNode expression, - ColumnStrategy strategy) { + @Nullable ColumnStrategy strategy) { super(pos); this.name = name; this.dataType = dataType; @@ -62,8 +76,10 @@ public class SqlColumnDeclaration extends SqlCall { return OPERATOR; } + @SuppressWarnings("nullness") @Override public List getOperandList() { - return ImmutableList.of(name, dataType); + return ImmutableNullableList.of(name, dataType, expression, + strategy != null ? new SqlIdentifier(strategy.name(), SqlParserPos.ZERO) : null); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { @@ -73,7 +89,7 @@ public class SqlColumnDeclaration extends SqlCall { writer.keyword("NOT NULL"); } SqlNode expression = this.expression; - if (expression != null) { + if (expression != null && strategy != null) { switch (strategy) { case VIRTUAL: case STORED: diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateForeignSchema.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateForeignSchema.java index 53e106b4d8fe..e7a4993d8d8d 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateForeignSchema.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateForeignSchema.java @@ -16,9 +16,11 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCreate; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.SqlOperator; @@ -51,8 +53,18 @@ public class SqlCreateForeignSchema extends SqlCreate { private final @Nullable SqlNodeList optionList; private static final SqlOperator OPERATOR = - new SqlSpecialOperator("CREATE FOREIGN SCHEMA", - SqlKind.CREATE_FOREIGN_SCHEMA); + new SqlSpecialOperator("CREATE FOREIGN SCHEMA", SqlKind.CREATE_FOREIGN_SCHEMA) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlCreateForeignSchema(pos, + ((SqlLiteral) requireNonNull(operands[0], "replace")).booleanValue(), + ((SqlLiteral) requireNonNull(operands[1], "ifNotExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[2], "name"), + operands[3], + operands[4], + (SqlNodeList) operands[5]); + } + }; /** Creates a SqlCreateForeignSchema. */ SqlCreateForeignSchema(SqlParserPos pos, boolean replace, boolean ifNotExists, @@ -69,7 +81,10 @@ public class SqlCreateForeignSchema extends SqlCreate { @SuppressWarnings("nullness") @Override public List getOperandList() { - return ImmutableNullableList.of(name, type, library, optionList); + return ImmutableNullableList.of( + SqlLiteral.createBoolean(getReplace(), SqlParserPos.ZERO), + SqlLiteral.createBoolean(ifNotExists, SqlParserPos.ZERO), + name, type, library, optionList); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateFunction.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateFunction.java index ae0abc289822..fb859b2013d0 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateFunction.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateFunction.java @@ -16,6 +16,7 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCreate; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; @@ -29,7 +30,10 @@ import org.apache.calcite.util.Pair; import org.apache.calcite.util.Util; -import java.util.Arrays; +import com.google.common.collect.ImmutableList; + +import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.List; import static com.google.common.base.Preconditions.checkArgument; @@ -44,8 +48,18 @@ public class SqlCreateFunction extends SqlCreate { private final SqlNode className; private final SqlNodeList usingList; - private static final SqlSpecialOperator OPERATOR = - new SqlSpecialOperator("CREATE FUNCTION", SqlKind.CREATE_FUNCTION); + private static final SqlOperator OPERATOR = + new SqlSpecialOperator("CREATE FUNCTION", SqlKind.CREATE_FUNCTION) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlCreateFunction(pos, + ((SqlLiteral) requireNonNull(operands[0], "replace")).booleanValue(), + ((SqlLiteral) requireNonNull(operands[1], "ifNotExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[2], "name"), + requireNonNull(operands[3], "className"), + (SqlNodeList) requireNonNull(operands[4], "usingList")); + } + }; /** Creates a SqlCreateFunction. */ public SqlCreateFunction(SqlParserPos pos, boolean replace, @@ -91,6 +105,9 @@ private List> pairs() { } @Override public List getOperandList() { - return Arrays.asList(name, className, usingList); + return ImmutableList.of( + SqlLiteral.createBoolean(getReplace(), SqlParserPos.ZERO), + SqlLiteral.createBoolean(ifNotExists, SqlParserPos.ZERO), + name, className, usingList); } } diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateMaterializedView.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateMaterializedView.java index a5ccd904db8a..3894cc276971 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateMaterializedView.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateMaterializedView.java @@ -16,9 +16,11 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCreate; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.SqlOperator; @@ -42,8 +44,17 @@ public class SqlCreateMaterializedView extends SqlCreate { public final SqlNode query; private static final SqlOperator OPERATOR = - new SqlSpecialOperator("CREATE MATERIALIZED VIEW", - SqlKind.CREATE_MATERIALIZED_VIEW); + new SqlSpecialOperator("CREATE MATERIALIZED VIEW", SqlKind.CREATE_MATERIALIZED_VIEW) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlCreateMaterializedView(pos, + ((SqlLiteral) requireNonNull(operands[0], "replace")).booleanValue(), + ((SqlLiteral) requireNonNull(operands[1], "ifNotExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[2], "name"), + (SqlNodeList) operands[3], + requireNonNull(operands[4], "query")); + } + }; /** Creates a SqlCreateView. */ SqlCreateMaterializedView(SqlParserPos pos, boolean replace, @@ -57,7 +68,10 @@ public class SqlCreateMaterializedView extends SqlCreate { @SuppressWarnings("nullness") @Override public List getOperandList() { - return ImmutableNullableList.of(name, columnList, query); + return ImmutableNullableList.of( + SqlLiteral.createBoolean(getReplace(), SqlParserPos.ZERO), + SqlLiteral.createBoolean(ifNotExists, SqlParserPos.ZERO), + name, columnList, query); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateSchema.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateSchema.java index ee405b0c2df1..d661daadc219 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateSchema.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateSchema.java @@ -16,9 +16,11 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCreate; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; @@ -26,6 +28,8 @@ import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.util.ImmutableNullableList; +import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.List; import static java.util.Objects.requireNonNull; @@ -37,7 +41,15 @@ public class SqlCreateSchema extends SqlCreate { public final SqlIdentifier name; private static final SqlOperator OPERATOR = - new SqlSpecialOperator("CREATE SCHEMA", SqlKind.CREATE_SCHEMA); + new SqlSpecialOperator("CREATE SCHEMA", SqlKind.CREATE_SCHEMA) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlCreateSchema(pos, + ((SqlLiteral) requireNonNull(operands[0], "replace")).booleanValue(), + ((SqlLiteral) requireNonNull(operands[1], "ifNotExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[2], "name")); + } + }; /** Creates a SqlCreateSchema. */ SqlCreateSchema(SqlParserPos pos, boolean replace, boolean ifNotExists, @@ -47,7 +59,10 @@ public class SqlCreateSchema extends SqlCreate { } @Override public List getOperandList() { - return ImmutableNullableList.of(name); + return ImmutableNullableList.of( + SqlLiteral.createBoolean(getReplace(), SqlParserPos.ZERO), + SqlLiteral.createBoolean(ifNotExists, SqlParserPos.ZERO), + name); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTable.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTable.java index 7e7dd144cbed..1bf283bf0cd6 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTable.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTable.java @@ -16,9 +16,11 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCreate; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.SqlOperator; @@ -42,7 +44,17 @@ public class SqlCreateTable extends SqlCreate { public final @Nullable SqlNode query; private static final SqlOperator OPERATOR = - new SqlSpecialOperator("CREATE TABLE", SqlKind.CREATE_TABLE); + new SqlSpecialOperator("CREATE TABLE", SqlKind.CREATE_TABLE) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlCreateTable(pos, + ((SqlLiteral) requireNonNull(operands[0], "replace")).booleanValue(), + ((SqlLiteral) requireNonNull(operands[1], "ifNotExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[2], "name"), + (SqlNodeList) requireNonNull(operands[3], "columnList"), + operands[4]); + } + }; /** Creates a SqlCreateTable. */ protected SqlCreateTable(SqlParserPos pos, boolean replace, boolean ifNotExists, @@ -55,7 +67,10 @@ protected SqlCreateTable(SqlParserPos pos, boolean replace, boolean ifNotExists, @SuppressWarnings("nullness") @Override public List getOperandList() { - return ImmutableNullableList.of(name, columnList, query); + return ImmutableNullableList.of( + SqlLiteral.createBoolean(getReplace(), SqlParserPos.ZERO), + SqlLiteral.createBoolean(ifNotExists, SqlParserPos.ZERO), + name, columnList, query); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTableLike.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTableLike.java index 957f87531dd4..225ae2d8d855 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTableLike.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTableLike.java @@ -16,6 +16,7 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCreate; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; @@ -29,6 +30,8 @@ import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.util.ImmutableNullableList; +import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.HashSet; import java.util.List; import java.util.Set; @@ -36,12 +39,25 @@ import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code CREATE TABLE LIKE} statement. */ public class SqlCreateTableLike extends SqlCreate { private static final SqlOperator OPERATOR = - new SqlSpecialOperator("CREATE TABLE LIKE", SqlKind.CREATE_TABLE_LIKE); + new SqlSpecialOperator("CREATE TABLE LIKE", SqlKind.CREATE_TABLE_LIKE) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlCreateTableLike(pos, + ((SqlLiteral) requireNonNull(operands[0], "replace")).booleanValue(), + ((SqlLiteral) requireNonNull(operands[1], "ifNotExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[2], "name"), + (SqlIdentifier) requireNonNull(operands[3], "sourceTable"), + (SqlNodeList) requireNonNull(operands[4], "includingOptions"), + (SqlNodeList) requireNonNull(operands[5], "excludingOptions")); + } + }; /** * The LikeOption specify which additional properties of the original table to copy. @@ -83,7 +99,10 @@ public SqlCreateTableLike(SqlParserPos pos, boolean replace, boolean ifNotExists } @Override public List getOperandList() { - return ImmutableNullableList.of(name, sourceTable, includingOptions, + return ImmutableNullableList.of( + SqlLiteral.createBoolean(getReplace(), SqlParserPos.ZERO), + SqlLiteral.createBoolean(ifNotExists, SqlParserPos.ZERO), + name, sourceTable, includingOptions, excludingOptions); } diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateType.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateType.java index 67188f736bfe..7e4dc1f632d8 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateType.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateType.java @@ -16,10 +16,12 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCreate; import org.apache.calcite.sql.SqlDataTypeSpec; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.SqlOperator; @@ -43,7 +45,16 @@ public class SqlCreateType extends SqlCreate { public final @Nullable SqlDataTypeSpec dataType; private static final SqlOperator OPERATOR = - new SqlSpecialOperator("CREATE TYPE", SqlKind.CREATE_TYPE); + new SqlSpecialOperator("CREATE TYPE", SqlKind.CREATE_TYPE) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlCreateType(pos, + ((SqlLiteral) requireNonNull(operands[0], "replace")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[1], "name"), + (SqlNodeList) operands[2], + (SqlDataTypeSpec) operands[3]); + } + }; /** Creates a SqlCreateType. */ SqlCreateType(SqlParserPos pos, boolean replace, SqlIdentifier name, @@ -56,7 +67,9 @@ public class SqlCreateType extends SqlCreate { @SuppressWarnings("nullness") @Override public List getOperandList() { - return ImmutableNullableList.of(name, attributeDefs); + return ImmutableNullableList.of( + SqlLiteral.createBoolean(getReplace(), SqlParserPos.ZERO), + name, attributeDefs, dataType); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateView.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateView.java index 662e86496693..38297f83e6a3 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateView.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateView.java @@ -16,9 +16,11 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCreate; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.SqlOperator; @@ -42,7 +44,16 @@ public class SqlCreateView extends SqlCreate { public final SqlNode query; private static final SqlOperator OPERATOR = - new SqlSpecialOperator("CREATE VIEW", SqlKind.CREATE_VIEW); + new SqlSpecialOperator("CREATE VIEW", SqlKind.CREATE_VIEW) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlCreateView(pos, + ((SqlLiteral) requireNonNull(operands[0], "replace")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[1], "name"), + (SqlNodeList) operands[3], + requireNonNull(operands[4], "query")); + } + }; /** Creates a SqlCreateView. */ SqlCreateView(SqlParserPos pos, boolean replace, SqlIdentifier name, @@ -55,7 +66,9 @@ public class SqlCreateView extends SqlCreate { @SuppressWarnings("nullness") @Override public List getOperandList() { - return ImmutableNullableList.of(name, columnList, query); + return ImmutableNullableList.of( + SqlLiteral.createBoolean(getReplace(), SqlParserPos.ZERO), + name, columnList, query); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropFunction.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropFunction.java index 9b24b030b9c9..a8601ba9d0f8 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropFunction.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropFunction.java @@ -16,18 +16,32 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; import org.apache.calcite.sql.parser.SqlParserPos; +import org.checkerframework.checker.nullness.qual.Nullable; + +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code DROP FUNCTION} statement. */ public class SqlDropFunction extends SqlDropObject { private static final SqlOperator OPERATOR = - new SqlSpecialOperator("DROP FUNCTION", SqlKind.DROP_FUNCTION); + new SqlSpecialOperator("DROP FUNCTION", SqlKind.DROP_FUNCTION) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlDropFunction(pos, + ((SqlLiteral) requireNonNull(operands[0], "ifExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[1], "name")); + } + }; /** Creates a SqlDropFunction. */ public SqlDropFunction(SqlParserPos pos, boolean ifExists, diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropMaterializedView.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropMaterializedView.java index 374167478a57..09807cbc96a8 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropMaterializedView.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropMaterializedView.java @@ -16,19 +16,32 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; import org.apache.calcite.sql.parser.SqlParserPos; +import org.checkerframework.checker.nullness.qual.Nullable; + +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code DROP MATERIALIZED VIEW} statement. */ public class SqlDropMaterializedView extends SqlDropObject { private static final SqlOperator OPERATOR = - new SqlSpecialOperator("DROP MATERIALIZED VIEW", - SqlKind.DROP_MATERIALIZED_VIEW); + new SqlSpecialOperator("DROP MATERIALIZED VIEW", SqlKind.DROP_MATERIALIZED_VIEW) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlDropMaterializedView(pos, + ((SqlLiteral) requireNonNull(operands[0], "ifExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[1], "name")); + } + }; /** Creates a SqlDropMaterializedView. */ SqlDropMaterializedView(SqlParserPos pos, boolean ifExists, diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropObject.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropObject.java index 278bde6ac82d..541fe7c4aac4 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropObject.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropObject.java @@ -19,6 +19,7 @@ import org.apache.calcite.jdbc.CalcitePrepare; import org.apache.calcite.sql.SqlDrop; import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlWriter; @@ -43,7 +44,9 @@ public abstract class SqlDropObject extends SqlDrop { } @Override public List getOperandList() { - return ImmutableList.of(name); + return ImmutableList.of( + SqlLiteral.createBoolean(ifExists, SqlParserPos.ZERO), + name); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropSchema.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropSchema.java index b06022977b67..95689c29ef25 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropSchema.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropSchema.java @@ -16,6 +16,7 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlDrop; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; @@ -28,8 +29,12 @@ import com.google.common.collect.ImmutableList; +import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.List; +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code DROP SCHEMA} statement. */ @@ -38,7 +43,15 @@ public class SqlDropSchema extends SqlDrop { public final SqlIdentifier name; private static final SqlOperator OPERATOR = - new SqlSpecialOperator("DROP SCHEMA", SqlKind.DROP_SCHEMA); + new SqlSpecialOperator("DROP SCHEMA", SqlKind.DROP_SCHEMA) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlDropSchema(pos, + ((SqlLiteral) requireNonNull(operands[0], "foreign")).booleanValue(), + ((SqlLiteral) requireNonNull(operands[1], "ifExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[2], "name")); + } + }; /** Creates a SqlDropSchema. */ SqlDropSchema(SqlParserPos pos, boolean foreign, boolean ifExists, @@ -50,7 +63,9 @@ public class SqlDropSchema extends SqlDrop { @Override public List getOperandList() { return ImmutableList.of( - SqlLiteral.createBoolean(foreign, SqlParserPos.ZERO), name); + SqlLiteral.createBoolean(foreign, SqlParserPos.ZERO), + SqlLiteral.createBoolean(ifExists, SqlParserPos.ZERO), + name); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropTable.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropTable.java index 4eab052ff07a..314686f1e310 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropTable.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropTable.java @@ -16,18 +16,32 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; import org.apache.calcite.sql.parser.SqlParserPos; +import org.checkerframework.checker.nullness.qual.Nullable; + +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code DROP TABLE} statement. */ public class SqlDropTable extends SqlDropObject { private static final SqlOperator OPERATOR = - new SqlSpecialOperator("DROP TABLE", SqlKind.DROP_TABLE); + new SqlSpecialOperator("DROP TABLE", SqlKind.DROP_TABLE) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlDropTable(pos, + ((SqlLiteral) requireNonNull(operands[0], "ifExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[1], "name")); + } + }; /** Creates a SqlDropTable. */ SqlDropTable(SqlParserPos pos, boolean ifExists, SqlIdentifier name) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropType.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropType.java index 17e29c287955..06ecf7427038 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropType.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropType.java @@ -16,18 +16,32 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; import org.apache.calcite.sql.parser.SqlParserPos; +import org.checkerframework.checker.nullness.qual.Nullable; + +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code DROP TYPE} statement. */ public class SqlDropType extends SqlDropObject { private static final SqlOperator OPERATOR = - new SqlSpecialOperator("DROP TYPE", SqlKind.DROP_TYPE); + new SqlSpecialOperator("DROP TYPE", SqlKind.DROP_TYPE) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlDropType(pos, + ((SqlLiteral) requireNonNull(operands[0], "ifExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[1], "name")); + } + }; SqlDropType(SqlParserPos pos, boolean ifExists, SqlIdentifier name) { super(OPERATOR, pos, ifExists, name); diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropView.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropView.java index b8de41d5ad0b..ff2d669a6810 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropView.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDropView.java @@ -16,18 +16,32 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; import org.apache.calcite.sql.parser.SqlParserPos; +import org.checkerframework.checker.nullness.qual.Nullable; + +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code DROP VIEW} statement. */ public class SqlDropView extends SqlDropObject { private static final SqlOperator OPERATOR = - new SqlSpecialOperator("DROP VIEW", SqlKind.DROP_VIEW); + new SqlSpecialOperator("DROP VIEW", SqlKind.DROP_VIEW) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlDropView(pos, + ((SqlLiteral) requireNonNull(operands[0], "ifExists")).booleanValue(), + (SqlIdentifier) requireNonNull(operands[1], "name")); + } + }; /** Creates a SqlDropView. */ SqlDropView(SqlParserPos pos, boolean ifExists, SqlIdentifier name) { diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlKeyConstraint.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlKeyConstraint.java index bc526e1d1516..37ad08be223e 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlKeyConstraint.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlKeyConstraint.java @@ -19,6 +19,7 @@ import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.SqlOperator; @@ -31,17 +32,33 @@ import java.util.List; +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code UNIQUE}, {@code PRIMARY KEY} constraints. * *

And {@code FOREIGN KEY}, when we support it. */ public class SqlKeyConstraint extends SqlCall { - private static final SqlSpecialOperator UNIQUE = - new SqlSpecialOperator("UNIQUE", SqlKind.UNIQUE); + private static final SqlOperator UNIQUE = + new SqlSpecialOperator("UNIQUE", SqlKind.UNIQUE) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return unique(pos, + (SqlIdentifier) requireNonNull(operands[0], "name"), + (SqlNodeList) requireNonNull(operands[1], "columnList")); + } + }; - protected static final SqlSpecialOperator PRIMARY = - new SqlSpecialOperator("PRIMARY KEY", SqlKind.PRIMARY_KEY); + protected static final SqlOperator PRIMARY = + new SqlSpecialOperator("PRIMARY KEY", SqlKind.PRIMARY_KEY) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return primary(pos, + (SqlIdentifier) requireNonNull(operands[0], "name"), + (SqlNodeList) requireNonNull(operands[1], "columnList")); + } + }; private final @Nullable SqlIdentifier name; private final SqlNodeList columnList; diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlTruncateTable.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlTruncateTable.java index 2d82107efc61..1c633c819f72 100644 --- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlTruncateTable.java +++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlTruncateTable.java @@ -16,8 +16,10 @@ */ package org.apache.calcite.sql.ddl; +import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; @@ -27,40 +29,51 @@ import com.google.common.collect.ImmutableList; +import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.List; +import static java.util.Objects.requireNonNull; + /** * Parse tree for {@code TRUNCATE TABLE} statement. */ public class SqlTruncateTable extends SqlTruncate { private static final SqlOperator OPERATOR = - new SqlSpecialOperator("TRUNCATE TABLE", SqlKind.TRUNCATE_TABLE); + new SqlSpecialOperator("TRUNCATE TABLE", SqlKind.TRUNCATE_TABLE) { + @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier, + SqlParserPos pos, @Nullable SqlNode... operands) { + return new SqlTruncateTable(pos, + (SqlIdentifier) requireNonNull(operands[0], "name"), + ((SqlLiteral) requireNonNull(operands[1], "continueIdentity")).booleanValue()); + } + }; + public final SqlIdentifier name; - public final boolean continueIdentify; + public final boolean continueIdentity; /** * Creates a SqlTruncateTable. */ - public SqlTruncateTable(SqlParserPos pos, SqlIdentifier name, boolean continueIdentify) { + public SqlTruncateTable(SqlParserPos pos, SqlIdentifier name, boolean continueIdentity) { super(OPERATOR, pos); this.name = name; - this.continueIdentify = continueIdentify; + this.continueIdentity = continueIdentity; } @Override public List getOperandList() { - return ImmutableList.of(name); + return ImmutableList.of(name, SqlLiteral.createBoolean(continueIdentity, SqlParserPos.ZERO)); } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { writer.keyword("TRUNCATE"); writer.keyword("TABLE"); name.unparse(writer, leftPrec, rightPrec); - if (continueIdentify) { + if (continueIdentity) { writer.keyword("CONTINUE IDENTITY"); } else { writer.keyword("RESTART IDENTITY"); - } } } diff --git a/core/src/test/java/org/apache/calcite/util/UtilTest.java b/core/src/test/java/org/apache/calcite/util/UtilTest.java index 45c964beedbb..7d8797f19caf 100644 --- a/core/src/test/java/org/apache/calcite/util/UtilTest.java +++ b/core/src/test/java/org/apache/calcite/util/UtilTest.java @@ -30,6 +30,7 @@ import org.apache.calcite.runtime.SqlFunctions; import org.apache.calcite.runtime.Utilities; import org.apache.calcite.sql.SqlCollation; +import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.dialect.CalciteSqlDialect; import org.apache.calcite.sql.fun.SqlLibrary; import org.apache.calcite.sql.util.IdPair; @@ -56,6 +57,7 @@ import org.hamcrest.StringDescription; import org.hamcrest.TypeSafeMatcher; import org.junit.jupiter.api.Test; +import org.locationtech.jts.util.Assert; import java.io.PrintWriter; import java.io.Serializable; @@ -2961,6 +2963,16 @@ private void checkNameMultimap(String s, NameMultimap map) { assertThat(s2, hasToString(s.toString())); } + @Test void testCollationEncoding() { + SqlCollation collation = + new SqlCollation( + SqlCollation.Coercibility.COERCIBLE, Locale.ENGLISH, + Util.getDefaultCharset(), "primary"); + SqlNodeList list = collation.asList(); + SqlCollation decoded = SqlCollation.fromSqlList(list); + Assert.equals(collation, decoded); + } + @Test void testXmlOutput() { final StringWriter w = new StringWriter(); final XmlOutput o = new XmlOutput(w); diff --git a/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java b/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java index 3fb4545643ba..8bd55b91519f 100644 --- a/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java +++ b/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java @@ -387,7 +387,7 @@ public void execute(SqlTruncateTable truncate, RESOURCE.tableNotFound(pair.right)); } - if (!truncate.continueIdentify) { + if (!truncate.continueIdentity) { // Calcite not support RESTART IDENTIFY throw new UnsupportedOperationException("RESTART IDENTIFY is not supported"); } @@ -519,7 +519,12 @@ public void execute(SqlCreateTable create, if (d.strategy != ColumnStrategy.VIRTUAL) { storedBuilder.add(d.name.getSimple(), type); } - b.add(ColumnDef.of(d.expression, type, d.strategy)); + final ColumnStrategy strategy = d.strategy != null + ? d.strategy + : type.isNullable() + ? ColumnStrategy.NULLABLE + : ColumnStrategy.NOT_NULLABLE; + b.add(ColumnDef.of(d.expression, type, strategy)); } else if (c.e instanceof SqlIdentifier) { final SqlIdentifier id = (SqlIdentifier) c.e; if (queryRowType == null) { diff --git a/server/src/test/java/org/apache/calcite/test/ServerParserTest.java b/server/src/test/java/org/apache/calcite/test/ServerParserTest.java index aeb1c0752569..99fa4f37d664 100644 --- a/server/src/test/java/org/apache/calcite/test/ServerParserTest.java +++ b/server/src/test/java/org/apache/calcite/test/ServerParserTest.java @@ -16,12 +16,36 @@ */ package org.apache.calcite.test; +import org.apache.calcite.sql.SqlCall; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.ddl.SqlCreateFunction; +import org.apache.calcite.sql.ddl.SqlCreateSchema; +import org.apache.calcite.sql.ddl.SqlCreateTable; +import org.apache.calcite.sql.ddl.SqlCreateType; +import org.apache.calcite.sql.ddl.SqlDropFunction; +import org.apache.calcite.sql.ddl.SqlDropMaterializedView; +import org.apache.calcite.sql.ddl.SqlDropSchema; +import org.apache.calcite.sql.ddl.SqlDropTable; +import org.apache.calcite.sql.ddl.SqlDropType; +import org.apache.calcite.sql.ddl.SqlDropView; +import org.apache.calcite.sql.ddl.SqlTruncateTable; +import org.apache.calcite.sql.parser.SqlParseException; import org.apache.calcite.sql.parser.SqlParserFixture; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.parser.SqlParserTest; import org.apache.calcite.sql.parser.ddl.SqlDdlParserImpl; +import org.apache.calcite.sql.util.SqlShuttle; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.jupiter.api.Test; +import java.util.function.BiConsumer; +import java.util.function.Function; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import static java.util.Objects.requireNonNull; + /** * Tests SQL parser extensions for DDL. * @@ -86,6 +110,83 @@ class ServerParserTest extends SqlParserTest { sql(sql).ok(expected); } + /** Test case for [CALCITE-7339] + * Most classes in SqlDdlNodes use an incorrect SqlCallFactory. */ + @Test void testShuttle() throws SqlParseException { + // A shuttle which modified a SqlCall's position + final SqlShuttle shuttle = new SqlShuttle() { + @Override public @Nullable SqlNode visit(SqlCall call) { + SqlNode newCall = super.visit(call); + return requireNonNull(newCall, "newCall").clone(SqlParserPos.ZERO); + } + }; + + BiConsumer> tester = + (fixture, function) -> { + SqlNode node = fixture.node(); + assertTrue(function.apply(node)); + SqlNode newNode = shuttle.visitNode(node); + assertTrue(function.apply(newNode)); + }; + + String sql = "CREATE TYPE T AS (x INT)"; + SqlParserFixture fixture = sql(sql); + fixture.ok("CREATE TYPE `T` AS (`X` INTEGER)"); + tester.accept(fixture, n -> n instanceof SqlCreateType); + + // The following also checks SqlCheckConstraint, SqlColumnDeclaration, SqlAttributeDefinition + sql = "CREATE TABLE X (I INTEGER NOT NULL, CONSTRAINT C1 CHECK (I < 10), J INTEGER)"; + fixture = sql(sql); + fixture.ok("CREATE TABLE `X` (`I` INTEGER NOT NULL, " + + "CONSTRAINT `C1` CHECK (`I` < 10), `J` INTEGER)"); + tester.accept(fixture, n -> n instanceof SqlCreateTable); + + sql = "CREATE FUNCTION F AS 'a.b'"; + fixture = sql(sql); + fixture.ok("CREATE FUNCTION `F` AS 'a.b'"); + tester.accept(fixture, n -> n instanceof SqlCreateFunction); + + sql = "CREATE SCHEMA F"; + fixture = sql(sql); + fixture.ok("CREATE SCHEMA `F`"); + tester.accept(fixture, n -> n instanceof SqlCreateSchema); + + sql = "DROP FUNCTION IF EXISTS F"; + fixture = sql(sql); + fixture.ok("DROP FUNCTION IF EXISTS `F`"); + tester.accept(fixture, n -> n instanceof SqlDropFunction); + + sql = "DROP VIEW IF EXISTS V"; + fixture = sql(sql); + fixture.ok("DROP VIEW IF EXISTS `V`"); + tester.accept(fixture, n -> n instanceof SqlDropView); + + sql = "DROP TABLE T"; + fixture = sql(sql); + fixture.ok("DROP TABLE `T`"); + tester.accept(fixture, n -> n instanceof SqlDropTable); + + sql = "DROP SCHEMA IF EXISTS S"; + fixture = sql(sql); + fixture.ok("DROP SCHEMA IF EXISTS `S`"); + tester.accept(fixture, n -> n instanceof SqlDropSchema); + + sql = "DROP TYPE IF EXISTS T"; + fixture = sql(sql); + fixture.ok("DROP TYPE IF EXISTS `T`"); + tester.accept(fixture, n -> n instanceof SqlDropType); + + sql = "DROP MATERIALIZED VIEW IF EXISTS V"; + fixture = sql(sql); + fixture.ok("DROP MATERIALIZED VIEW IF EXISTS `V`"); + tester.accept(fixture, n -> n instanceof SqlDropMaterializedView); + + sql = "TRUNCATE TABLE T CONTINUE IDENTITY"; + fixture = sql(sql); + fixture.ok("TRUNCATE TABLE `T` CONTINUE IDENTITY"); + tester.accept(fixture, n -> n instanceof SqlTruncateTable); + } + @Test void testCreateForeignSchema2() { final String sql = "create or replace foreign schema x\n" + "library 'com.example.ExampleSchemaFactory'\n"