@Override
public Expression visitLeave(LikeParseNode node, List<Expression> children) throws SQLException {
ParseNode lhsNode = node.getChildren().get(0);
ParseNode rhsNode = node.getChildren().get(1);
Expression lhs = children.get(0);
Expression rhs = children.get(1);
if ( rhs.getDataType() != null && lhs.getDataType() != null &&
!lhs.getDataType().isCoercibleTo(rhs.getDataType()) &&
!rhs.getDataType().isCoercibleTo(lhs.getDataType())) {
throw TypeMismatchException.newException(lhs.getDataType(), rhs.getDataType(), node.toString());
}
if (lhsNode instanceof BindParseNode) {
context.getBindManager().addParamMetaData((BindParseNode)lhsNode, rhs);
}
if (rhsNode instanceof BindParseNode) {
context.getBindManager().addParamMetaData((BindParseNode)rhsNode, lhs);
}
if (rhs instanceof LiteralExpression) {
String pattern = (String)((LiteralExpression)rhs).getValue();
if (pattern == null || pattern.length() == 0) {
return LiteralExpression.newConstant(null, rhs.isDeterministic());
}
// TODO: for pattern of '%' optimize to strlength(lhs) > 0
// We can't use lhs IS NOT NULL b/c if lhs is NULL we need
// to return NULL.
int index = LikeExpression.indexOfWildcard(pattern);
// Can't possibly be as long as the constant, then FALSE
Integer lhsByteSize = lhs.getByteSize();
if (lhsByteSize != null && lhsByteSize < index) {
return LiteralExpression.newConstant(false, rhs.isDeterministic());
}
if (index == -1) {
String rhsLiteral = LikeExpression.unescapeLike(pattern);
if (lhsByteSize != null && lhsByteSize != rhsLiteral.length()) {
return LiteralExpression.newConstant(false, rhs.isDeterministic());
}
CompareOp op = node.isNegate() ? CompareOp.NOT_EQUAL : CompareOp.EQUAL;
if (pattern.equals(rhsLiteral)) {
return new ComparisonExpression(op, children);
} else {
rhs = LiteralExpression.newConstant(rhsLiteral, PDataType.CHAR, rhs.isDeterministic());
return new ComparisonExpression(op, Arrays.asList(lhs,rhs));
}
}
}
Expression expression = new LikeExpression(children);
if (node.isStateless()) {
ImmutableBytesWritable ptr = context.getTempPtr();
if (!expression.evaluate(null, ptr)) {
return LiteralExpression.newConstant(null, expression.isDeterministic());
} else {
return LiteralExpression.newConstant(Boolean.TRUE.equals(PDataType.BOOLEAN.toObject(ptr)) ^ node.isNegate(), expression.isDeterministic());
}
}
if (node.isNegate()) {
expression = new NotExpression(expression);
}