|
39 | 39 | import io.prestosql.sql.tree.InListExpression; |
40 | 40 | import io.prestosql.sql.tree.InPredicate; |
41 | 41 | import io.prestosql.sql.tree.IsNullPredicate; |
| 42 | +import io.prestosql.sql.tree.LikePredicate; |
42 | 43 | import io.prestosql.sql.tree.Literal; |
43 | 44 | import io.prestosql.sql.tree.LongLiteral; |
44 | 45 | import io.prestosql.sql.tree.NotExpression; |
|
56 | 57 | import java.math.BigDecimal; |
57 | 58 | import java.util.Arrays; |
58 | 59 | import java.util.List; |
| 60 | +import java.util.Optional; |
59 | 61 | import java.util.concurrent.TimeUnit; |
60 | 62 |
|
61 | 63 | import static io.airlift.slice.Slices.utf8Slice; |
|
77 | 79 | import static io.prestosql.spi.type.TinyintType.TINYINT; |
78 | 80 | import static io.prestosql.spi.type.VarbinaryType.VARBINARY; |
79 | 81 | import static io.prestosql.spi.type.VarcharType.VARCHAR; |
| 82 | +import static io.prestosql.spi.type.VarcharType.createUnboundedVarcharType; |
80 | 83 | import static io.prestosql.sql.ExpressionUtils.and; |
81 | 84 | import static io.prestosql.sql.ExpressionUtils.or; |
82 | 85 | import static io.prestosql.sql.analyzer.TypeSignatureTranslator.toSqlType; |
@@ -1457,6 +1460,128 @@ private void testNumericTypeTranslation(NumericValues<?> columnValues, NumericVa |
1457 | 1460 | } |
1458 | 1461 | } |
1459 | 1462 |
|
| 1463 | + @Test |
| 1464 | + public void testLikePredicate() |
| 1465 | + { |
| 1466 | + Type varcharType = createUnboundedVarcharType(); |
| 1467 | + |
| 1468 | + // constant |
| 1469 | + testSimpleComparison( |
| 1470 | + like(C_VARCHAR, stringLiteral("abc")), |
| 1471 | + C_VARCHAR, |
| 1472 | + Domain.multipleValues(varcharType, ImmutableList.of(utf8Slice("abc")))); |
| 1473 | + |
| 1474 | + // starts with pattern |
| 1475 | + assertUnsupportedPredicate(like(C_VARCHAR, stringLiteral("_def"))); |
| 1476 | + assertUnsupportedPredicate(like(C_VARCHAR, stringLiteral("%def"))); |
| 1477 | + |
| 1478 | + // _ pattern (unless escaped) |
| 1479 | + testSimpleComparison( |
| 1480 | + like(C_VARCHAR, stringLiteral("abc_def")), |
| 1481 | + C_VARCHAR, |
| 1482 | + like(C_VARCHAR, stringLiteral("abc_def")), |
| 1483 | + Domain.create(ValueSet.ofRanges(Range.range(varcharType, utf8Slice("abc"), true, utf8Slice("abd"), false)), false)); |
| 1484 | + |
| 1485 | + testSimpleComparison( |
| 1486 | + like(C_VARCHAR, stringLiteral("abc\\_def")), |
| 1487 | + C_VARCHAR, |
| 1488 | + like(C_VARCHAR, stringLiteral("abc\\_def")), |
| 1489 | + Domain.create(ValueSet.ofRanges(Range.range(varcharType, utf8Slice("abc\\"), true, utf8Slice("abc]"), false)), false)); |
| 1490 | + |
| 1491 | + testSimpleComparison( |
| 1492 | + like(C_VARCHAR, stringLiteral("abc\\_def"), stringLiteral("\\")), |
| 1493 | + C_VARCHAR, |
| 1494 | + Domain.multipleValues(varcharType, ImmutableList.of(utf8Slice("abc_def")))); |
| 1495 | + |
| 1496 | + testSimpleComparison( |
| 1497 | + like(C_VARCHAR, stringLiteral("abc\\_def_"), stringLiteral("\\")), |
| 1498 | + C_VARCHAR, |
| 1499 | + like(C_VARCHAR, stringLiteral("abc\\_def_"), stringLiteral("\\")), |
| 1500 | + Domain.create(ValueSet.ofRanges(Range.range(varcharType, utf8Slice("abc_def"), true, utf8Slice("abc_deg"), false)), false)); |
| 1501 | + |
| 1502 | + testSimpleComparison( |
| 1503 | + like(C_VARCHAR, stringLiteral("abc^_def_"), stringLiteral("^")), |
| 1504 | + C_VARCHAR, |
| 1505 | + like(C_VARCHAR, stringLiteral("abc^_def_"), stringLiteral("^")), |
| 1506 | + Domain.create(ValueSet.ofRanges(Range.range(varcharType, utf8Slice("abc_def"), true, utf8Slice("abc_deg"), false)), false)); |
| 1507 | + |
| 1508 | + // % pattern (unless escaped) |
| 1509 | + testSimpleComparison( |
| 1510 | + like(C_VARCHAR, stringLiteral("abc%")), |
| 1511 | + C_VARCHAR, |
| 1512 | + like(C_VARCHAR, stringLiteral("abc%")), |
| 1513 | + Domain.create(ValueSet.ofRanges(Range.range(varcharType, utf8Slice("abc"), true, utf8Slice("abd"), false)), false)); |
| 1514 | + |
| 1515 | + testSimpleComparison( |
| 1516 | + like(C_VARCHAR, stringLiteral("abc%def")), |
| 1517 | + C_VARCHAR, |
| 1518 | + like(C_VARCHAR, stringLiteral("abc%def")), |
| 1519 | + Domain.create(ValueSet.ofRanges(Range.range(varcharType, utf8Slice("abc"), true, utf8Slice("abd"), false)), false)); |
| 1520 | + |
| 1521 | + testSimpleComparison( |
| 1522 | + like(C_VARCHAR, stringLiteral("abc\\%def")), |
| 1523 | + C_VARCHAR, |
| 1524 | + like(C_VARCHAR, stringLiteral("abc\\%def")), |
| 1525 | + Domain.create(ValueSet.ofRanges(Range.range(varcharType, utf8Slice("abc\\"), true, utf8Slice("abc]"), false)), false)); |
| 1526 | + |
| 1527 | + testSimpleComparison( |
| 1528 | + like(C_VARCHAR, stringLiteral("abc\\%def"), stringLiteral("\\")), |
| 1529 | + C_VARCHAR, |
| 1530 | + Domain.multipleValues(varcharType, ImmutableList.of(utf8Slice("abc%def")))); |
| 1531 | + |
| 1532 | + testSimpleComparison( |
| 1533 | + like(C_VARCHAR, stringLiteral("abc\\%def_"), stringLiteral("\\")), |
| 1534 | + C_VARCHAR, |
| 1535 | + like(C_VARCHAR, stringLiteral("abc\\%def_"), stringLiteral("\\")), |
| 1536 | + Domain.create(ValueSet.ofRanges(Range.range(varcharType, utf8Slice("abc%def"), true, utf8Slice("abc%deg"), false)), false)); |
| 1537 | + |
| 1538 | + testSimpleComparison( |
| 1539 | + like(C_VARCHAR, stringLiteral("abc^%def_"), stringLiteral("^")), |
| 1540 | + C_VARCHAR, |
| 1541 | + like(C_VARCHAR, stringLiteral("abc^%def_"), stringLiteral("^")), |
| 1542 | + Domain.create(ValueSet.ofRanges(Range.range(varcharType, utf8Slice("abc%def"), true, utf8Slice("abc%deg"), false)), false)); |
| 1543 | + |
| 1544 | + // non-ASCII literal |
| 1545 | + testSimpleComparison( |
| 1546 | + like(C_VARCHAR, stringLiteral("abc\u007f\u0123\udbfe")), |
| 1547 | + C_VARCHAR, |
| 1548 | + Domain.multipleValues(varcharType, ImmutableList.of(utf8Slice("abc\u007f\u0123\udbfe")))); |
| 1549 | + |
| 1550 | + // non-ASCII prefix |
| 1551 | + testSimpleComparison( |
| 1552 | + like(C_VARCHAR, stringLiteral("abc\u0123\ud83d\ude80def\u007e\u007f\u00ff\u0123\uccf0%")), |
| 1553 | + C_VARCHAR, |
| 1554 | + like(C_VARCHAR, stringLiteral("abc\u0123\ud83d\ude80def\u007e\u007f\u00ff\u0123\uccf0%")), |
| 1555 | + Domain.create( |
| 1556 | + ValueSet.ofRanges(Range.range(varcharType, |
| 1557 | + utf8Slice("abc\u0123\ud83d\ude80def\u007e\u007f\u00ff\u0123\uccf0"), true, |
| 1558 | + utf8Slice("abc\u0123\ud83d\ude80def\u007f"), false)), |
| 1559 | + false)); |
| 1560 | + |
| 1561 | + // dynamic escape |
| 1562 | + assertUnsupportedPredicate(like(C_VARCHAR, stringLiteral("abc\\_def"), C_VARCHAR_1.toSymbolReference())); |
| 1563 | + |
| 1564 | + // negation with literal |
| 1565 | + testSimpleComparison( |
| 1566 | + not(like(C_VARCHAR, stringLiteral("abcdef"))), |
| 1567 | + C_VARCHAR, |
| 1568 | + Domain.create(ValueSet.ofRanges( |
| 1569 | + Range.lessThan(varcharType, utf8Slice("abcdef")), |
| 1570 | + Range.greaterThan(varcharType, utf8Slice("abcdef"))), |
| 1571 | + false)); |
| 1572 | + |
| 1573 | + testSimpleComparison( |
| 1574 | + not(like(C_VARCHAR, stringLiteral("abc\\_def"), stringLiteral("\\"))), |
| 1575 | + C_VARCHAR, |
| 1576 | + Domain.create(ValueSet.ofRanges( |
| 1577 | + Range.lessThan(varcharType, utf8Slice("abc_def")), |
| 1578 | + Range.greaterThan(varcharType, utf8Slice("abc_def"))), |
| 1579 | + false)); |
| 1580 | + |
| 1581 | + // negation with pattern |
| 1582 | + assertUnsupportedPredicate(not(like(C_VARCHAR, stringLiteral("abc\\_def")))); |
| 1583 | + } |
| 1584 | + |
1460 | 1585 | @Test |
1461 | 1586 | public void testCharComparedToVarcharExpression() |
1462 | 1587 | { |
@@ -1568,6 +1693,16 @@ private static ComparisonExpression isDistinctFrom(Symbol symbol, Expression exp |
1568 | 1693 | return isDistinctFrom(symbol.toSymbolReference(), expression); |
1569 | 1694 | } |
1570 | 1695 |
|
| 1696 | + private static LikePredicate like(Symbol symbol, Expression expression) |
| 1697 | + { |
| 1698 | + return new LikePredicate(symbol.toSymbolReference(), expression, Optional.empty()); |
| 1699 | + } |
| 1700 | + |
| 1701 | + private static LikePredicate like(Symbol symbol, Expression expression, Expression escape) |
| 1702 | + { |
| 1703 | + return new LikePredicate(symbol.toSymbolReference(), expression, Optional.of(escape)); |
| 1704 | + } |
| 1705 | + |
1571 | 1706 | private static Expression isNotNull(Symbol symbol) |
1572 | 1707 | { |
1573 | 1708 | return isNotNull(symbol.toSymbolReference()); |
@@ -1733,14 +1868,19 @@ private void testSimpleComparison(Expression expression, Symbol symbol, Range ex |
1733 | 1868 | testSimpleComparison(expression, symbol, Domain.create(ValueSet.ofRanges(expectedDomainRange), false)); |
1734 | 1869 | } |
1735 | 1870 |
|
1736 | | - private void testSimpleComparison(Expression expression, Symbol symbol, Domain domain) |
| 1871 | + private void testSimpleComparison(Expression expression, Symbol symbol, Domain expectedDomain) |
| 1872 | + { |
| 1873 | + testSimpleComparison(expression, symbol, TRUE_LITERAL, expectedDomain); |
| 1874 | + } |
| 1875 | + |
| 1876 | + private void testSimpleComparison(Expression expression, Symbol symbol, Expression expectedRemainingExpression, Domain expectedDomain) |
1737 | 1877 | { |
1738 | 1878 | ExtractionResult result = fromPredicate(expression); |
1739 | | - assertEquals(result.getRemainingExpression(), TRUE_LITERAL); |
| 1879 | + assertEquals(result.getRemainingExpression(), expectedRemainingExpression); |
1740 | 1880 | TupleDomain<Symbol> actual = result.getTupleDomain(); |
1741 | | - TupleDomain<Symbol> expected = withColumnDomains(ImmutableMap.of(symbol, domain)); |
| 1881 | + TupleDomain<Symbol> expected = withColumnDomains(ImmutableMap.of(symbol, expectedDomain)); |
1742 | 1882 | if (!actual.equals(expected)) { |
1743 | | - fail(format("for comparison [%s] expected %s but found %s", expression.toString(), expected.toString(SESSION), actual.toString(SESSION))); |
| 1883 | + fail(format("for comparison [%s] expected [%s] but found [%s]", expression.toString(), expected.toString(SESSION), actual.toString(SESSION))); |
1744 | 1884 | } |
1745 | 1885 | } |
1746 | 1886 |
|
|
0 commit comments