diff --git a/presto-main/src/main/java/com/facebook/presto/sql/planner/planPrinter/RowExpressionFormatter.java b/presto-main/src/main/java/com/facebook/presto/sql/planner/planPrinter/RowExpressionFormatter.java index 31104dcff1f0b..0e7ff8a26aec2 100644 --- a/presto-main/src/main/java/com/facebook/presto/sql/planner/planPrinter/RowExpressionFormatter.java +++ b/presto-main/src/main/java/com/facebook/presto/sql/planner/planPrinter/RowExpressionFormatter.java @@ -85,20 +85,25 @@ else if (standardFunctionResolution.isBetweenFunction(node.getFunctionHandle())) } else if (standardFunctionResolution.isLikeFunction(node.getFunctionHandle())) { RowExpression value = node.getArguments().get(0); - CallExpression patternCallExpression = (CallExpression) node.getArguments().get(1); - - // second LIKE argument is: - // CAST(pattern as LikePattern), if escape is not present - // LIKE_PATTERN(pattern, escape), if escape is present - if (standardFunctionResolution.isCastFunction(patternCallExpression.getFunctionHandle())) { - RowExpression pattern = patternCallExpression.getArguments().get(0); - return String.format("%s LIKE %s", formatRowExpression(session, value), formatRowExpression(session, pattern)); - } - else { - RowExpression pattern = patternCallExpression.getArguments().get(0); - RowExpression escape = patternCallExpression.getArguments().get(1); - return String.format("%s LIKE %s ESCAPE %s", formatRowExpression(session, value), formatRowExpression(session, pattern), formatRowExpression(session, escape)); + RowExpression patternRowExpression = node.getArguments().get(1); + + if (patternRowExpression instanceof CallExpression) { + CallExpression patternCallExpression = (CallExpression) patternRowExpression; + // second LIKE argument is: + // CAST(pattern as LikePattern), if escape is not present + // LIKE_PATTERN(pattern, escape), if escape is present + if (standardFunctionResolution.isCastFunction(patternCallExpression.getFunctionHandle())) { + RowExpression pattern = patternCallExpression.getArguments().get(0); + return String.format("%s LIKE %s", formatRowExpression(session, value), formatRowExpression(session, pattern)); + } + else if (standardFunctionResolution.isLikePatternFunction(patternCallExpression.getFunctionHandle())) { + RowExpression pattern = patternCallExpression.getArguments().get(0); + RowExpression escape = patternCallExpression.getArguments().get(1); + return String.format("%s LIKE %s ESCAPE %s", formatRowExpression(session, value), formatRowExpression(session, pattern), formatRowExpression(session, escape)); + } } + + return String.format("%s LIKE %s", formatRowExpression(session, value), formatRowExpression(session, patternRowExpression)); } FunctionMetadata metadata = functionMetadataManager.getFunctionMetadata(node.getFunctionHandle()); return node.getDisplayName() + (metadata.getVersion().hasVersion() ? ":" + metadata.getVersion() : "") + "(" + String.join(", ", formatRowExpressions(session, node.getArguments())) + ")"; diff --git a/presto-main/src/main/java/com/facebook/presto/sql/relational/FunctionResolution.java b/presto-main/src/main/java/com/facebook/presto/sql/relational/FunctionResolution.java index a90c27c2e6a87..30ef42396c9bd 100644 --- a/presto-main/src/main/java/com/facebook/presto/sql/relational/FunctionResolution.java +++ b/presto-main/src/main/java/com/facebook/presto/sql/relational/FunctionResolution.java @@ -86,16 +86,24 @@ public FunctionHandle likeCharFunction(Type valueType) return functionAndTypeManager.lookupFunction("LIKE", fromTypes(valueType, LIKE_PATTERN)); } + @Override public boolean isLikeFunction(FunctionHandle functionHandle) { return functionAndTypeManager.getFunctionMetadata(functionHandle).getName().equals(QualifiedObjectName.valueOf(DEFAULT_NAMESPACE, "LIKE")); } + @Override public FunctionHandle likePatternFunction() { return functionAndTypeManager.lookupFunction("LIKE_PATTERN", fromTypes(VARCHAR, VARCHAR)); } + @Override + public boolean isLikePatternFunction(FunctionHandle functionHandle) + { + return functionAndTypeManager.getFunctionMetadata(functionHandle).getName().equals(QualifiedObjectName.valueOf(DEFAULT_NAMESPACE, "LIKE_PATTERN")); + } + @Override public boolean isCastFunction(FunctionHandle functionHandle) { diff --git a/presto-main/src/test/java/com/facebook/presto/sql/planner/TestRowExpressionFormatter.java b/presto-main/src/test/java/com/facebook/presto/sql/planner/TestRowExpressionFormatter.java index d6f52b2ab0d17..b92751c70d0d7 100644 --- a/presto-main/src/test/java/com/facebook/presto/sql/planner/TestRowExpressionFormatter.java +++ b/presto-main/src/test/java/com/facebook/presto/sql/planner/TestRowExpressionFormatter.java @@ -21,12 +21,14 @@ import com.facebook.presto.common.type.Type; import com.facebook.presto.metadata.CastType; import com.facebook.presto.metadata.FunctionAndTypeManager; +import com.facebook.presto.metadata.MetadataManager; import com.facebook.presto.spi.relation.CallExpression; import com.facebook.presto.spi.relation.RowExpression; import com.facebook.presto.spi.relation.SpecialFormExpression; import com.facebook.presto.spi.relation.VariableReferenceExpression; import com.facebook.presto.sql.planner.planPrinter.RowExpressionFormatter; import com.facebook.presto.sql.relational.FunctionResolution; +import com.facebook.presto.sql.relational.RowExpressionOptimizer; import com.google.common.collect.ImmutableList; import com.google.common.io.BaseEncoding; import io.airlift.slice.Slice; @@ -65,6 +67,7 @@ import static com.facebook.presto.common.type.VarbinaryType.VARBINARY; import static com.facebook.presto.common.type.VarcharType.VARCHAR; import static com.facebook.presto.metadata.FunctionAndTypeManager.createTestFunctionAndTypeManager; +import static com.facebook.presto.spi.relation.ExpressionOptimizer.Level.OPTIMIZED; import static com.facebook.presto.spi.relation.SpecialFormExpression.Form.AND; import static com.facebook.presto.spi.relation.SpecialFormExpression.Form.IS_NULL; import static com.facebook.presto.spi.relation.SpecialFormExpression.Form.OR; @@ -72,6 +75,7 @@ import static com.facebook.presto.sql.relational.Expressions.call; import static com.facebook.presto.sql.relational.Expressions.constant; import static com.facebook.presto.sql.relational.Expressions.constantNull; +import static com.facebook.presto.testing.TestingConnectorSession.SESSION; import static com.facebook.presto.type.ColorType.COLOR; import static com.facebook.presto.type.IntervalDayTimeType.INTERVAL_DAY_TIME; import static com.facebook.presto.type.IntervalYearMonthType.INTERVAL_YEAR_MONTH; @@ -79,6 +83,7 @@ import static io.airlift.slice.Slices.utf8Slice; import static java.lang.Float.floatToIntBits; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; public class TestRowExpressionFormatter { @@ -88,6 +93,7 @@ public class TestRowExpressionFormatter private static final VariableReferenceExpression C_BIGINT = new VariableReferenceExpression("c_bigint", BIGINT); private static final VariableReferenceExpression C_BIGINT_ARRAY = new VariableReferenceExpression("c_bigint_array", new ArrayType(BIGINT)); private static final VariableReferenceExpression C_VARCHAR = new VariableReferenceExpression("c_varchar", VARCHAR); + private static final RowExpressionOptimizer OPTIMIZER = new RowExpressionOptimizer(MetadataManager.createTestMetadataManager()); @Test public void testConstants() @@ -255,6 +261,9 @@ public void testCalls() constant(utf8Slice("prefix%"), VARCHAR))); assertEquals(format(callExpression), "c_varchar LIKE VARCHAR'prefix%'"); + callExpression = OPTIMIZER.optimize(callExpression, OPTIMIZED, SESSION); + assertTrue(format(callExpression).startsWith("c_varchar LIKE LIKEPATTERN'io.airlift.joni.Regex@")); + // like escape callExpression = call( "LIKE", @@ -268,6 +277,9 @@ public void testCalls() constant(utf8Slice("%escaped$_"), VARCHAR), constant(utf8Slice("$"), VARCHAR))); assertEquals(format(callExpression), "c_varchar LIKE VARCHAR'%escaped$_' ESCAPE VARCHAR'$'"); + + callExpression = OPTIMIZER.optimize(callExpression, OPTIMIZED, SESSION); + assertTrue(format(callExpression).startsWith("c_varchar LIKE LIKEPATTERN'io.airlift.joni.Regex@")); } @Test diff --git a/presto-spi/src/main/java/com/facebook/presto/spi/function/StandardFunctionResolution.java b/presto-spi/src/main/java/com/facebook/presto/spi/function/StandardFunctionResolution.java index 8cfb0a05d6788..27c50edce7b40 100644 --- a/presto-spi/src/main/java/com/facebook/presto/spi/function/StandardFunctionResolution.java +++ b/presto-spi/src/main/java/com/facebook/presto/spi/function/StandardFunctionResolution.java @@ -34,6 +34,10 @@ public interface StandardFunctionResolution boolean isLikeFunction(FunctionHandle functionHandle); + FunctionHandle likePatternFunction(); + + boolean isLikePatternFunction(FunctionHandle functionHandle); + FunctionHandle arrayConstructor(List argumentTypes); FunctionHandle arithmeticFunction(OperatorType operator, Type leftType, Type rightType);