Skip to content

Commit

Permalink
[CALCITE-4059] SqlTypeUtil#equalSansNullability consider Array/Map ty…
Browse files Browse the repository at this point in the history
…pe (Jiatao Tao)

close apache#2019
  • Loading branch information
Aaaaaaron authored and danny0405 committed Jul 3, 2020
1 parent 2ef46dc commit a329e88
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 2 deletions.
82 changes: 80 additions & 2 deletions core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.Util;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;

Expand Down Expand Up @@ -1160,6 +1161,54 @@ public static boolean equalSansNullability(
factory.createTypeWithNullability(type2, type1.isNullable()));
}

/**
* Returns whether two collection types are equal, ignoring nullability.
*
* <p>They need not come from the same factory.
*
* @param factory Type factory
* @param type1 First type
* @param type2 Second type
* @return Whether types are equal, ignoring nullability
*/
public static boolean equalAsCollectionSansNullability(
RelDataTypeFactory factory,
RelDataType type1,
RelDataType type2) {
Preconditions.checkArgument(isCollection(type1),
"Input type must be collection type");
Preconditions.checkArgument(isCollection(type2),
"Input type must be collection type");

return (type1 == type2)
|| (type1.getSqlTypeName() == type2.getSqlTypeName()
&& equalSansNullability(factory, type1.getComponentType(), type2.getComponentType()));
}

/**
* Returns whether two map types are equal, ignoring nullability.
*
* <p>They need not come from the same factory.
*
* @param factory Type factory
* @param type1 First type
* @param type2 Second type
* @return Whether types are equal, ignoring nullability
*/
public static boolean equalAsMapSansNullability(
RelDataTypeFactory factory,
RelDataType type1,
RelDataType type2) {
Preconditions.checkArgument(isMap(type1), "Input type must be map type");
Preconditions.checkArgument(isMap(type2), "Input type must be map type");

MapSqlType mType1 = (MapSqlType) type1;
MapSqlType mType2 = (MapSqlType) type2;
return (type1 == type2)
|| (equalSansNullability(factory, mType1.getKeyType(), mType2.getKeyType())
&& equalSansNullability(factory, mType1.getValueType(), mType2.getValueType()));
}

/**
* Returns whether two struct types are equal, ignoring nullability.
*
Expand All @@ -1178,8 +1227,12 @@ public static boolean equalAsStructSansNullability(
RelDataType type1,
RelDataType type2,
SqlNameMatcher nameMatcher) {
assert type1.isStruct();
assert type2.isStruct();
Preconditions.checkArgument(type1.isStruct(), "Input type must be struct type");
Preconditions.checkArgument(type2.isStruct(), "Input type must be struct type");

if (type1 == type2) {
return true;
}

if (type1.getFieldCount() != type2.getFieldCount()) {
return false;
Expand Down Expand Up @@ -1510,6 +1563,31 @@ public static boolean isMap(RelDataType type) {
return type.getSqlTypeName() == SqlTypeName.MAP;
}

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

return type.getSqlTypeName() == SqlTypeName.MULTISET;
}

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

return type.getSqlTypeName() == SqlTypeName.ARRAY
|| type.getSqlTypeName() == SqlTypeName.MULTISET;
}

/**
* @return true if type is CHARACTER
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class SqlTypeFixture {
typeFactory.createMultisetType(sqlFloat, -1), false);
final RelDataType multisetBigInt = typeFactory.createTypeWithNullability(
typeFactory.createMultisetType(sqlBigIntNullable, -1), false);
final RelDataType multisetBigIntNullable = typeFactory.createTypeWithNullability(
typeFactory.createMultisetType(sqlBigIntNullable, -1), true);
final RelDataType arrayBigIntNullable = typeFactory.createTypeWithNullability(
typeFactory.createArrayType(sqlBigIntNullable, -1), true);
final RelDataType arrayOfArrayBigInt = typeFactory.createTypeWithNullability(
Expand All @@ -72,4 +74,8 @@ class SqlTypeFixture {
typeFactory.createStructType(
ImmutableList.of(sqlInt, sqlInt),
ImmutableList.of("i", "j")), true);
final RelDataType mapOfInt = typeFactory.createTypeWithNullability(
typeFactory.createMapType(sqlInt, sqlInt), false);
final RelDataType mapOfIntNullable = typeFactory.createTypeWithNullability(
typeFactory.createMapType(sqlInt, sqlInt), true);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import org.junit.jupiter.api.Test;

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

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -117,6 +119,28 @@ class SqlTypeUtilTest {
SqlTypeCoercionRule.THREAD_PROVIDERS.set(defaultRules);
}

@Test void testEqualAsCollectionSansNullability() {
// case array
assertThat(
equalAsCollectionSansNullability(f.typeFactory, f.arrayBigInt, f.arrayBigIntNullable),
is(true));

// case multiset
assertThat(
equalAsCollectionSansNullability(f.typeFactory, f.multisetBigInt, f.multisetBigIntNullable),
is(true));

// multiset and array are not equal.
assertThat(
equalAsCollectionSansNullability(f.typeFactory, f.arrayBigInt, f.multisetBigInt),
is(false));
}

@Test void testEqualAsMapSansNullability() {
assertThat(
equalAsMapSansNullability(f.typeFactory, f.mapOfInt, f.mapOfIntNullable), is(true));
}

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 a329e88

Please sign in to comment.