Skip to content

Commit dc34938

Browse files
xin-zhang2martint
andcommitted
feat(optimizer): Unwrap casts in comparison expressions
Changes adapted from trino/PR#731 Original commit: 4729bc9 e23e317 48336f2 Author: Martin Traverso Co-authored-by: Martin Traverso <[email protected]>
1 parent 7eb2686 commit dc34938

File tree

18 files changed

+1565
-2
lines changed

18 files changed

+1565
-2
lines changed

presto-common/src/main/java/com/facebook/presto/common/type/AbstractVarcharType.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
import com.facebook.presto.common.block.BlockBuilder;
1919
import com.facebook.presto.common.function.SqlFunctionProperties;
2020
import io.airlift.slice.Slice;
21+
import io.airlift.slice.SliceUtf8;
2122
import io.airlift.slice.Slices;
2223

2324
import java.util.Objects;
25+
import java.util.Optional;
26+
27+
import static java.lang.Character.MAX_CODE_POINT;
2428

2529
public class AbstractVarcharType
2630
extends AbstractVariableWidthType
@@ -106,6 +110,27 @@ public int compareTo(Block leftBlock, int leftPosition, Block rightBlock, int ri
106110
return leftBlock.compareTo(leftPosition, 0, leftLength, rightBlock, rightPosition, 0, rightLength);
107111
}
108112

113+
@Override
114+
public Optional<Range> getRange()
115+
{
116+
if (length > 100) {
117+
// The max/min values may be materialized in the plan, so we don't want them to be too large.
118+
// Range comparison against large values are usually nonsensical, too, so no need to support them
119+
// beyond a certain size. They specific choice above is arbitrary and can be adjusted if needed.
120+
return Optional.empty();
121+
}
122+
123+
int codePointSize = SliceUtf8.lengthOfCodePoint(MAX_CODE_POINT);
124+
125+
Slice max = Slices.allocate(codePointSize * length);
126+
int position = 0;
127+
for (int i = 0; i < length; i++) {
128+
position += SliceUtf8.setCodePointAt(MAX_CODE_POINT, max, position);
129+
}
130+
131+
return Optional.of(new Range(Slices.EMPTY_SLICE, max));
132+
}
133+
109134
@Override
110135
public void appendTo(Block block, int position, BlockBuilder blockBuilder)
111136
{

presto-common/src/main/java/com/facebook/presto/common/type/BigintType.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import com.facebook.presto.common.block.Block;
1717
import com.facebook.presto.common.function.SqlFunctionProperties;
1818

19+
import java.util.Optional;
20+
1921
import static com.facebook.presto.common.type.TypeSignature.parseTypeSignature;
2022

2123
public final class BigintType
@@ -50,4 +52,10 @@ public int hashCode()
5052
{
5153
return getClass().hashCode();
5254
}
55+
56+
@Override
57+
public Optional<Range> getRange()
58+
{
59+
return Optional.of(new Range(Long.MIN_VALUE, Long.MAX_VALUE));
60+
}
5361
}

presto-common/src/main/java/com/facebook/presto/common/type/DoubleType.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import com.facebook.presto.common.block.UncheckedBlock;
2222
import com.facebook.presto.common.function.SqlFunctionProperties;
2323

24+
import java.util.Optional;
25+
2426
import static com.facebook.presto.common.type.TypeSignature.parseTypeSignature;
2527
import static com.facebook.presto.common.type.TypeUtils.doubleCompare;
2628
import static com.facebook.presto.common.type.TypeUtils.doubleEquals;
@@ -170,4 +172,12 @@ public int hashCode()
170172
{
171173
return getClass().hashCode();
172174
}
175+
176+
@Override
177+
public Optional<Range> getRange()
178+
{
179+
// The range for double is undefined because NaN is a special value that
180+
// is *not* in any reasonable definition of a range for this type.
181+
return Optional.empty();
182+
}
173183
}

presto-common/src/main/java/com/facebook/presto/common/type/IntegerType.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import com.facebook.presto.common.block.BlockBuilder;
1919
import com.facebook.presto.common.function.SqlFunctionProperties;
2020

21+
import java.util.Optional;
22+
2123
import static com.facebook.presto.common.type.TypeSignature.parseTypeSignature;
2224
import static java.lang.String.format;
2325

@@ -54,6 +56,12 @@ else if (value < Integer.MIN_VALUE) {
5456
blockBuilder.writeInt((int) value).closeEntry();
5557
}
5658

59+
@Override
60+
public Optional<Range> getRange()
61+
{
62+
return Optional.of(new Range((long) Integer.MIN_VALUE, (long) Integer.MAX_VALUE));
63+
}
64+
5765
@Override
5866
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
5967
public boolean equals(Object other)

presto-common/src/main/java/com/facebook/presto/common/type/RealType.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import com.facebook.presto.common.block.BlockBuilder;
1919
import com.facebook.presto.common.function.SqlFunctionProperties;
2020

21+
import java.util.Optional;
22+
2123
import static com.facebook.presto.common.type.TypeSignature.parseTypeSignature;
2224
import static com.facebook.presto.common.type.TypeUtils.realCompare;
2325
import static com.facebook.presto.common.type.TypeUtils.realEquals;
@@ -106,4 +108,12 @@ public int hashCode()
106108
{
107109
return getClass().hashCode();
108110
}
111+
112+
@Override
113+
public Optional<Range> getRange()
114+
{
115+
// The range for real is undefined because NaN is a special value that
116+
// is *not* in any reasonable definition of a range for this type.
117+
return Optional.empty();
118+
}
109119
}

presto-common/src/main/java/com/facebook/presto/common/type/SmallintType.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import com.facebook.presto.common.block.UncheckedBlock;
2323
import com.facebook.presto.common.function.SqlFunctionProperties;
2424

25+
import java.util.Optional;
26+
2527
import static com.facebook.presto.common.type.TypeSignature.parseTypeSignature;
2628
import static java.lang.Long.rotateLeft;
2729
import static java.lang.String.format;
@@ -116,6 +118,12 @@ public int compareTo(Block leftBlock, int leftPosition, Block rightBlock, int ri
116118
return Short.compare(leftValue, rightValue);
117119
}
118120

121+
@Override
122+
public Optional<Range> getRange()
123+
{
124+
return Optional.of(new Range((long) Short.MIN_VALUE, (long) Short.MAX_VALUE));
125+
}
126+
119127
@Override
120128
public void appendTo(Block block, int position, BlockBuilder blockBuilder)
121129
{

presto-common/src/main/java/com/facebook/presto/common/type/TinyintType.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import com.facebook.presto.common.block.UncheckedBlock;
2323
import com.facebook.presto.common.function.SqlFunctionProperties;
2424

25+
import java.util.Optional;
26+
2527
import static com.facebook.presto.common.type.TypeSignature.parseTypeSignature;
2628
import static java.lang.Long.rotateLeft;
2729
import static java.lang.String.format;
@@ -116,6 +118,12 @@ public int compareTo(Block leftBlock, int leftPosition, Block rightBlock, int ri
116118
return Byte.compare(leftValue, rightValue);
117119
}
118120

121+
@Override
122+
public Optional<Range> getRange()
123+
{
124+
return Optional.of(new Range((long) Byte.MIN_VALUE, (long) Byte.MAX_VALUE));
125+
}
126+
119127
@Override
120128
public void appendTo(Block block, int position, BlockBuilder blockBuilder)
121129
{

presto-common/src/main/java/com/facebook/presto/common/type/Type.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
import io.airlift.slice.Slice;
2323

2424
import java.util.List;
25+
import java.util.Optional;
26+
27+
import static java.util.Objects.requireNonNull;
2528

2629
public interface Type
2730
{
@@ -194,4 +197,36 @@ default boolean equalValuesAreIdentical()
194197
* Compare the values in the specified block at the specified positions equal.
195198
*/
196199
int compareTo(Block leftBlock, int leftPosition, Block rightBlock, int rightPosition);
200+
201+
/**
202+
* Return the range of possible values for this type, if available.
203+
*
204+
* The type of the values must match {@link #getJavaType}
205+
*/
206+
default Optional<Range> getRange()
207+
{
208+
return Optional.empty();
209+
}
210+
211+
final class Range
212+
{
213+
private final Object min;
214+
private final Object max;
215+
216+
public Range(Object min, Object max)
217+
{
218+
this.min = requireNonNull(min, "min is null");
219+
this.max = requireNonNull(max, "max is null");
220+
}
221+
222+
public Object getMin()
223+
{
224+
return min;
225+
}
226+
227+
public Object getMax()
228+
{
229+
return max;
230+
}
231+
}
197232
}

presto-main-base/src/main/java/com/facebook/presto/SystemSessionProperties.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ public final class SystemSessionProperties
346346
public static final String UTILIZE_UNIQUE_PROPERTY_IN_QUERY_PLANNING = "utilize_unique_property_in_query_planning";
347347
public static final String PUSHDOWN_SUBFIELDS_FOR_MAP_FUNCTIONS = "pushdown_subfields_for_map_functions";
348348
public static final String MAX_SERIALIZABLE_OBJECT_SIZE = "max_serializable_object_size";
349+
public static final String UNWRAP_CASTS = "unwrap_casts";
349350

350351
// TODO: Native execution related session properties that are temporarily put here. They will be relocated in the future.
351352
public static final String NATIVE_AGGREGATION_SPILL_ALL = "native_aggregation_spill_all";
@@ -1993,6 +1994,10 @@ public SystemSessionProperties(
19931994
booleanProperty(ADD_DISTINCT_BELOW_SEMI_JOIN_BUILD,
19941995
"Add distinct aggregation below semi join build",
19951996
featuresConfig.isAddDistinctBelowSemiJoinBuild(),
1997+
false),
1998+
booleanProperty(UNWRAP_CASTS,
1999+
"Enable optimization to unwrap CAST expression",
2000+
featuresConfig.isUnwrapCasts(),
19962001
false));
19972002
}
19982003

@@ -3394,4 +3399,9 @@ public static long getMaxSerializableObjectSize(Session session)
33943399
{
33953400
return session.getSystemProperty(MAX_SERIALIZABLE_OBJECT_SIZE, Long.class);
33963401
}
3402+
3403+
public static boolean isUnwrapCasts(Session session)
3404+
{
3405+
return session.getSystemProperty(UNWRAP_CASTS, Boolean.class);
3406+
}
33973407
}

presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/FeaturesConfig.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ public class FeaturesConfig
321321

322322
private boolean builtInSidecarFunctionsEnabled;
323323

324+
private boolean unwrapCasts = true;
325+
324326
public enum PartitioningPrecisionStrategy
325327
{
326328
// Let Presto decide when to repartition
@@ -3194,4 +3196,16 @@ public boolean isBuiltInSidecarFunctionsEnabled()
31943196
{
31953197
return this.builtInSidecarFunctionsEnabled;
31963198
}
3199+
3200+
public boolean isUnwrapCasts()
3201+
{
3202+
return unwrapCasts;
3203+
}
3204+
3205+
@Config("optimizer.unwrap-casts")
3206+
public FeaturesConfig setUnwrapCasts(boolean unwrapCasts)
3207+
{
3208+
this.unwrapCasts = unwrapCasts;
3209+
return this;
3210+
}
31973211
}

0 commit comments

Comments
 (0)