Skip to content

Commit

Permalink
[CALCITE-4066] SqlTypeUtil#convertTypeToSpec cover Array/Multiset/Row…
Browse files Browse the repository at this point in the history
… types (Jiatao Tao)

close #2029
  • Loading branch information
Aaaaaaron authored and danny0405 committed Jul 3, 2020
1 parent a329e88 commit 8db7c9d
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 12 deletions.
61 changes: 49 additions & 12 deletions core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
Expand Up @@ -21,13 +21,18 @@
import org.apache.calcite.rel.type.RelDataTypeFamily;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
import org.apache.calcite.rel.type.RelRecordType;
import org.apache.calcite.rex.RexUtil;
import org.apache.calcite.sql.SqlBasicTypeNameSpec;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlCallBinding;
import org.apache.calcite.sql.SqlCollation;
import org.apache.calcite.sql.SqlCollectionTypeNameSpec;
import org.apache.calcite.sql.SqlDataTypeSpec;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlRowTypeNameSpec;
import org.apache.calcite.sql.SqlTypeNameSpec;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.validate.SqlNameMatcher;
import org.apache.calcite.sql.validate.SqlValidator;
Expand Down Expand Up @@ -1039,19 +1044,40 @@ public static SqlDataTypeSpec convertTypeToSpec(RelDataType type,
// interval types, multiset types, etc
assert typeName != null;

int precision = typeName.allowsPrec() ? type.getPrecision() : -1;
// fix up the precision.
if (maxPrecision > 0 && precision > maxPrecision) {
precision = maxPrecision;
final SqlTypeNameSpec typeNameSpec;
if (isAtomic(type)) {
int precision = typeName.allowsPrec() ? type.getPrecision() : -1;
// fix up the precision.
if (maxPrecision > 0 && precision > maxPrecision) {
precision = maxPrecision;
}
int scale = typeName.allowsScale() ? type.getScale() : -1;

typeNameSpec = new SqlBasicTypeNameSpec(
typeName,
precision,
scale,
charSetName,
SqlParserPos.ZERO);
} else if (isCollection(type)) {
typeNameSpec = new SqlCollectionTypeNameSpec(
convertTypeToSpec(type.getComponentType()).getTypeNameSpec(),
typeName,
SqlParserPos.ZERO);
} else if (isRow(type)) {
RelRecordType recordType = (RelRecordType) type;
List<RelDataTypeField> fields = recordType.getFieldList();
List<SqlIdentifier> fieldNames = fields.stream()
.map(f -> new SqlIdentifier(f.getName(), SqlParserPos.ZERO))
.collect(Collectors.toList());
List<SqlDataTypeSpec> fieldTypes = fields.stream()
.map(f -> convertTypeToSpec(f.getType()))
.collect(Collectors.toList());
typeNameSpec = new SqlRowTypeNameSpec(SqlParserPos.ZERO, fieldNames, fieldTypes);
} else {
throw new UnsupportedOperationException(
"Unsupported type when convertTypeToSpec: " + typeName);
}
int scale = typeName.allowsScale() ? type.getScale() : -1;

final SqlBasicTypeNameSpec typeNameSpec = new SqlBasicTypeNameSpec(
typeName,
precision,
scale,
charSetName,
SqlParserPos.ZERO);

// REVIEW jvs 28-Dec-2004: discriminate between precision/scale
// zero and unspecified?
Expand Down Expand Up @@ -1551,6 +1577,17 @@ public static boolean isArray(RelDataType type) {
return type.getSqlTypeName() == SqlTypeName.ARRAY;
}

/**
* @return true if type is ROW
*/
public static boolean isRow(RelDataType type) {
SqlTypeName typeName = type.getSqlTypeName();
if (typeName == null) {
return false;
}
return type.getSqlTypeName() == SqlTypeName.ROW;
}

/**
* @return true if type is MAP
*/
Expand Down
Expand Up @@ -18,12 +18,21 @@

import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.sql.SqlBasicTypeNameSpec;
import org.apache.calcite.sql.SqlCollectionTypeNameSpec;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlRowTypeNameSpec;

import com.google.common.collect.ImmutableList;

import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static org.apache.calcite.sql.type.SqlTypeUtil.areSameFamily;
import static org.apache.calcite.sql.type.SqlTypeUtil.convertTypeToSpec;
import static org.apache.calcite.sql.type.SqlTypeUtil.equalAsCollectionSansNullability;
import static org.apache.calcite.sql.type.SqlTypeUtil.equalAsMapSansNullability;

Expand Down Expand Up @@ -141,6 +150,36 @@ class SqlTypeUtilTest {
equalAsMapSansNullability(f.typeFactory, f.mapOfInt, f.mapOfIntNullable), is(true));
}

@Test void testConvertTypeToSpec() {
SqlBasicTypeNameSpec basicSpec =
(SqlBasicTypeNameSpec) convertTypeToSpec(f.sqlBigInt).getTypeNameSpec();
assertThat(basicSpec.getTypeName().getSimple(), is("BIGINT"));

SqlCollectionTypeNameSpec arraySpec =
(SqlCollectionTypeNameSpec) convertTypeToSpec(f.arrayBigInt).getTypeNameSpec();
assertThat(arraySpec.getTypeName().getSimple(), is("ARRAY"));
assertThat(arraySpec.getElementTypeName().getTypeName().getSimple(), is("BIGINT"));

SqlCollectionTypeNameSpec multisetSpec =
(SqlCollectionTypeNameSpec) convertTypeToSpec(f.multisetBigInt).getTypeNameSpec();
assertThat(multisetSpec.getTypeName().getSimple(), is("MULTISET"));
assertThat(multisetSpec.getElementTypeName().getTypeName().getSimple(), is("BIGINT"));

SqlRowTypeNameSpec rowSpec =
(SqlRowTypeNameSpec) convertTypeToSpec(f.structOfInt).getTypeNameSpec();
List<String> fieldNames = rowSpec.getFieldNames()
.stream()
.map(SqlIdentifier::getSimple)
.collect(Collectors.toList());
List<String> fieldTypeNames = rowSpec.getFieldTypes()
.stream()
.map(f -> f.getTypeName().getSimple())
.collect(Collectors.toList());
assertThat(rowSpec.getTypeName().getSimple(), is("ROW"));
assertThat(fieldNames, is(Arrays.asList("i", "j")));
assertThat(fieldTypeNames, is(Arrays.asList("INTEGER", "INTEGER")));
}

private RelDataType struct(RelDataType...relDataTypes) {
final RelDataTypeFactory.Builder builder = f.typeFactory.builder();
for (int i = 0; i < relDataTypes.length; i++) {
Expand Down

0 comments on commit 8db7c9d

Please sign in to comment.