public RelDataType createType(Type type) {
   if (type instanceof RelDataType) {
     return (RelDataType) type;
   }
   if (type instanceof SyntheticRecordType) {
     final SyntheticRecordType syntheticRecordType = (SyntheticRecordType) type;
     return syntheticRecordType.relType;
   }
   if (type instanceof Types.ArrayType) {
     final Types.ArrayType arrayType = (Types.ArrayType) type;
     final RelDataType componentRelType = createType(arrayType.getComponentType());
     return createArrayType(
         createTypeWithNullability(componentRelType, arrayType.componentIsNullable()),
         arrayType.maximumCardinality());
   }
   if (type instanceof Types.MapType) {
     final Types.MapType mapType = (Types.MapType) type;
     final RelDataType keyRelType = createType(mapType.getKeyType());
     final RelDataType valueRelType = createType(mapType.getValueType());
     return createMapType(
         createTypeWithNullability(keyRelType, mapType.keyIsNullable()),
         createTypeWithNullability(valueRelType, mapType.valueIsNullable()));
   }
   if (!(type instanceof Class)) {
     throw new UnsupportedOperationException("TODO: implement " + type);
   }
   final Class clazz = (Class) type;
   switch (Primitive.flavor(clazz)) {
     case PRIMITIVE:
       return createJavaType(clazz);
     case BOX:
       return createJavaType(Primitive.ofBox(clazz).boxClass);
   }
   if (JavaToSqlTypeConversionRules.instance().lookup(clazz) != null) {
     return createJavaType(clazz);
   } else if (clazz.isArray()) {
     return createMultisetType(createType(clazz.getComponentType()), -1);
   } else if (List.class.isAssignableFrom(clazz)) {
     return createArrayType(createTypeWithNullability(createSqlType(SqlTypeName.ANY), true), -1);
   } else if (Map.class.isAssignableFrom(clazz)) {
     return createMapType(
         createTypeWithNullability(createSqlType(SqlTypeName.ANY), true),
         createTypeWithNullability(createSqlType(SqlTypeName.ANY), true));
   } else {
     return createStructType(clazz);
   }
 }