@Override public boolean isOrderable() { return elementType.isOrderable(); }
Builder(Type type) { requireNonNull(type, "type is null"); if (!type.isOrderable()) { throw new IllegalArgumentException("Type is not orderable: " + type); } this.type = type; }
private SortedRangeSet(Type type, NavigableMap<Marker, Range> lowIndexedRanges) { requireNonNull(type, "type is null"); requireNonNull(lowIndexedRanges, "lowIndexedRanges is null"); if (!type.isOrderable()) { throw new IllegalArgumentException("Type is not orderable: " + type); } this.type = type; this.lowIndexedRanges = lowIndexedRanges; }
@Override public boolean isOrderable() { return fields.stream().allMatch(field -> field.getType().isOrderable()); }
@JsonCreator public EquatableValueSet( @JsonProperty("type") Type type, @JsonProperty("whiteList") boolean whiteList, @JsonProperty("entries") Set<ValueEntry> entries) { requireNonNull(type, "type is null"); requireNonNull(entries, "entries is null"); if (!type.isComparable()) { throw new IllegalArgumentException("Type is not comparable: " + type); } if (type.isOrderable()) { throw new IllegalArgumentException("Use SortedRangeSet instead"); } this.type = type; this.whiteList = whiteList; this.entries = Collections.unmodifiableSet(new HashSet<>(entries)); }
static ValueSet copyOf(Type type, Collection<Object> values) { if (type.isOrderable()) { return SortedRangeSet.copyOf(type, values.stream() .map(value -> Range.equal(type, value)) .collect(toList())); } if (type.isComparable()) { return EquatableValueSet.copyOf(type, values); } throw new IllegalArgumentException("Cannot create discrete ValueSet with non-comparable type: " + type); }
public boolean canBind(Type type) { if (comparableRequired && !type.isComparable()) { return false; } if (orderableRequired && !type.isOrderable()) { return false; } if (variadicBound != null && !type.getTypeSignature().getBase().equals(variadicBound)) { return false; } return true; }
static ValueSet of(Type type, Object first, Object... rest) { if (type.isOrderable()) { return SortedRangeSet.of(type, first, rest); } if (type.isComparable()) { return EquatableValueSet.of(type, first, rest); } throw new IllegalArgumentException("Cannot create discrete ValueSet with non-comparable type: " + type); }
public boolean canBind(Type type) { if (comparableRequired && !type.isComparable()) { return false; } if (orderableRequired && !type.isOrderable()) { return false; } if (variadicBound != null && !type.getTypeSignature().getBase().equals(variadicBound)) { return false; } return true; }
private boolean satisfiesConstraints(Type type) { if (comparableRequired && !type.isComparable()) { return false; } if (orderableRequired && !type.isOrderable()) { return false; } if (requiredBaseName.isPresent() && !UNKNOWN.equals(type) && !requiredBaseName.get().equals(type.getTypeSignature().getBase())) { // TODO: the case below should be properly handled: // * `type` does not have the `requiredBaseName` but can be coerced to some type that has the `requiredBaseName`. return false; } return true; } }
private boolean satisfiesConstraints(Type type) { if (comparableRequired && !type.isComparable()) { return false; } if (orderableRequired && !type.isOrderable()) { return false; } if (requiredBaseName.isPresent() && !UNKNOWN.equals(type) && !requiredBaseName.get().equals(type.getTypeSignature().getBase())) { // TODO: the case below should be properly handled: // * `type` does not have the `requiredBaseName` but can be coerced to some type that has the `requiredBaseName`. return false; } return true; } }
@Override public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type type = boundVariables.getTypeVariable("E"); checkArgument(type.isOrderable(), "Type must be orderable"); MethodHandle compareMethod = functionRegistry.getScalarFunctionImplementation(internalOperator(operatorType, BOOLEAN, ImmutableList.of(type, type))).getMethodHandle(); List<Class<?>> javaTypes = IntStream.range(0, arity) .mapToObj(i -> type.getJavaType()) .collect(toImmutableList()); Class<?> clazz = generate(javaTypes, type, compareMethod); MethodHandle methodHandle = methodHandle(clazz, getSignature().getName(), javaTypes.toArray(new Class<?>[javaTypes.size()])); return new ScalarFunctionImplementation( false, nCopies(javaTypes.size(), valueTypeArgumentProperty(RETURN_NULL_ON_NULL)), methodHandle, isDeterministic()); }
static ValueSet none(Type type) { if (type.isOrderable()) { return SortedRangeSet.none(type); } if (type.isComparable()) { return EquatableValueSet.none(type); } return AllOrNoneValueSet.none(type); }
@Override public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type type = boundVariables.getTypeVariable("E"); checkArgument(type.isOrderable(), "Type must be orderable"); MethodHandle compareMethod = functionRegistry.getScalarFunctionImplementation(internalOperator(operatorType, BOOLEAN, ImmutableList.of(type, type))).getMethodHandle(); List<Class<?>> javaTypes = IntStream.range(0, arity) .mapToObj(i -> type.getJavaType()) .collect(toImmutableList()); Class<?> clazz = generate(javaTypes, type, compareMethod); MethodHandle methodHandle = methodHandle(clazz, getSignature().getName(), javaTypes.toArray(new Class<?>[javaTypes.size()])); return new ScalarFunctionImplementation( false, nCopies(javaTypes.size(), valueTypeArgumentProperty(RETURN_NULL_ON_NULL)), methodHandle, isDeterministic()); }
static ValueSet all(Type type) { if (type.isOrderable()) { return SortedRangeSet.all(type); } if (type.isComparable()) { return EquatableValueSet.all(type); } return AllOrNoneValueSet.all(type); }
@Override public int compareTo(Block leftBlock, int leftPosition, Block rightBlock, int rightPosition) { Block leftRow = leftBlock.getObject(leftPosition, Block.class); Block rightRow = rightBlock.getObject(rightPosition, Block.class); for (int i = 0; i < leftRow.getPositionCount(); i++) { checkElementNotNull(leftRow.isNull(i)); checkElementNotNull(rightRow.isNull(i)); Type fieldType = fields.get(i).getType(); if (!fieldType.isOrderable()) { throw new UnsupportedOperationException(fieldType.getTypeSignature() + " type is not orderable"); } int compareResult = fieldType.compareTo(leftRow, i, rightRow, i); if (compareResult != 0) { return compareResult; } } return 0; }
@Test public void testOperatorsImplemented() { for (Type type : typeRegistry.getTypes()) { if (type.isComparable()) { functionRegistry.resolveOperator(EQUAL, ImmutableList.of(type, type)); functionRegistry.resolveOperator(NOT_EQUAL, ImmutableList.of(type, type)); functionRegistry.resolveOperator(IS_DISTINCT_FROM, ImmutableList.of(type, type)); functionRegistry.resolveOperator(HASH_CODE, ImmutableList.of(type)); } if (type.isOrderable()) { functionRegistry.resolveOperator(LESS_THAN, ImmutableList.of(type, type)); functionRegistry.resolveOperator(LESS_THAN_OR_EQUAL, ImmutableList.of(type, type)); functionRegistry.resolveOperator(GREATER_THAN_OR_EQUAL, ImmutableList.of(type, type)); functionRegistry.resolveOperator(GREATER_THAN, ImmutableList.of(type, type)); } } }
@Test public void testOperatorsImplemented() { for (Type type : typeRegistry.getTypes()) { if (type.isComparable()) { functionRegistry.resolveOperator(EQUAL, ImmutableList.of(type, type)); functionRegistry.resolveOperator(NOT_EQUAL, ImmutableList.of(type, type)); functionRegistry.resolveOperator(IS_DISTINCT_FROM, ImmutableList.of(type, type)); functionRegistry.resolveOperator(HASH_CODE, ImmutableList.of(type)); } if (type.isOrderable()) { functionRegistry.resolveOperator(LESS_THAN, ImmutableList.of(type, type)); functionRegistry.resolveOperator(LESS_THAN_OR_EQUAL, ImmutableList.of(type, type)); functionRegistry.resolveOperator(GREATER_THAN_OR_EQUAL, ImmutableList.of(type, type)); functionRegistry.resolveOperator(GREATER_THAN, ImmutableList.of(type, type)); } } }
@Override protected Type visitQuantifiedComparisonExpression(QuantifiedComparisonExpression node, StackableAstVisitorContext<Context> context) { Expression value = node.getValue(); process(value, context); Expression subquery = node.getSubquery(); process(subquery, context); Type comparisonType = coerceToSingleType(context, node, "Value expression and result of subquery must be of the same type for quantified comparison: %s vs %s", value, subquery); switch (node.getOperator()) { case LESS_THAN: case LESS_THAN_OR_EQUAL: case GREATER_THAN: case GREATER_THAN_OR_EQUAL: if (!comparisonType.isOrderable()) { throw new SemanticException(TYPE_MISMATCH, node, "Type [%s] must be orderable in order to be used in quantified comparison", comparisonType); } break; case EQUAL: case NOT_EQUAL: if (!comparisonType.isComparable()) { throw new SemanticException(TYPE_MISMATCH, node, "Type [%s] must be comparable in order to be used in quantified comparison", comparisonType); } break; default: throw new IllegalStateException(format("Unexpected comparison type: %s", node.getOperator())); } return setExpressionType(node, BOOLEAN); }
@Override public int compareTo(Block leftBlock, int leftPosition, Block rightBlock, int rightPosition) { if (!elementType.isOrderable()) { throw new UnsupportedOperationException(getTypeSignature() + " type is not orderable"); } Block leftArray = leftBlock.getObject(leftPosition, Block.class); Block rightArray = rightBlock.getObject(rightPosition, Block.class); int len = Math.min(leftArray.getPositionCount(), rightArray.getPositionCount()); int index = 0; while (index < len) { checkElementNotNull(leftArray.isNull(index), ARRAY_NULL_ELEMENT_MSG); checkElementNotNull(rightArray.isNull(index), ARRAY_NULL_ELEMENT_MSG); int comparison = elementType.compareTo(leftArray, index, rightArray, index); if (comparison != 0) { return comparison; } index++; } if (index == len) { return leftArray.getPositionCount() - rightArray.getPositionCount(); } return 0; }