/*
* Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. Crate licenses
* this file to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial agreement.
*/
package io.crate.operation.operator.any;
import io.crate.action.sql.SessionContext;
import io.crate.analyze.symbol.Function;
import io.crate.analyze.symbol.Literal;
import io.crate.analyze.symbol.Symbol;
import io.crate.metadata.FunctionImplementation;
import io.crate.metadata.TransactionContext;
import io.crate.data.Input;
import io.crate.operation.predicate.NotPredicate;
import io.crate.test.integration.CrateUnitTest;
import io.crate.types.ArrayType;
import io.crate.types.DataTypes;
import org.apache.lucene.util.BytesRef;
import org.junit.Test;
import java.util.Arrays;
import static org.hamcrest.Matchers.is;
public class AnyLikeOperatorTest extends CrateUnitTest {
private static Symbol normalizeSymbol(String pattern, String... expressions) {
Literal patternLiteral = Literal.of(pattern);
Object[] value = new Object[expressions.length];
for (int i = 0; i < expressions.length; i++) {
value[i] = expressions[i] == null ? null : new BytesRef(expressions[i]);
}
Literal valuesLiteral = Literal.of(new ArrayType(DataTypes.STRING), value);
AnyLikeOperator impl = (AnyLikeOperator) new AnyLikeOperator.AnyLikeResolver().getForTypes(
Arrays.asList(patternLiteral.valueType(), valuesLiteral.valueType())
);
Function function = new Function(
impl.info(),
Arrays.<Symbol>asList(patternLiteral, valuesLiteral)
);
return impl.normalizeSymbol(function, new TransactionContext(SessionContext.SYSTEM_SESSION));
}
private Boolean anyLikeNormalize(String pattern, String... expressions) {
return (Boolean) ((Literal) normalizeSymbol(pattern, expressions)).value();
}
private Boolean anyLike(String pattern, String... expressions) {
Literal patternLiteral = Literal.of(pattern);
Object[] value = new Object[expressions.length];
for (int i = 0; i < expressions.length; i++) {
value[i] = expressions[i] == null ? null : new BytesRef(expressions[i]);
}
Literal valuesLiteral = Literal.of(new ArrayType(DataTypes.STRING), value);
AnyLikeOperator impl = (AnyLikeOperator) new AnyLikeOperator.AnyLikeResolver().getForTypes(
Arrays.asList(DataTypes.STRING, valuesLiteral.valueType())
);
return impl.evaluate(patternLiteral, valuesLiteral);
}
@Test
public void testNormalizeSingleSymbolEqual() {
assertTrue(anyLikeNormalize("foo", "foo"));
assertFalse(anyLikeNormalize("notFoo", "foo"));
}
@Test
public void testNormalizeSymbolLikeZeroOrMore() {
// Following tests: wildcard: '%' ... zero or more characters (0...N)
assertTrue(anyLikeNormalize("%bar", "foobar", "bar"));
assertTrue(anyLikeNormalize("%bar", "bar"));
assertFalse(anyLikeNormalize("%bar", "ar", "car"));
assertTrue(anyLikeNormalize("foo%", "foobar", "kuhbar"));
assertTrue(anyLikeNormalize("foo%", "foo", "kuh"));
assertFalse(anyLikeNormalize("foo%", "fo", "kuh"));
assertTrue(anyLikeNormalize("%oob%", "foobar"));
}
@Test
public void testNormalizeSymbolLikeExactlyOne() {
// Following tests: wildcard: '_' ... any single character (exactly one)
assertTrue(anyLikeNormalize("_ar", "bar"));
assertFalse(anyLikeNormalize("_bar", "bar"));
assertTrue(anyLikeNormalize("fo_", "foo", "for"));
assertTrue(anyLikeNormalize("foo_", "foo", "foot"));
assertFalse(anyLikeNormalize("foo_", "foo"));
assertTrue(anyLikeNormalize("_o_", "foo"));
assertFalse(anyLikeNormalize("_foobar_", "foobar"));
}
// Following tests: mixed wildcards:
@Test
public void testNormalizeSymbolLikeMixed() {
assertTrue(anyLikeNormalize("%o_ar", "foobar", "foobaz"));
assertTrue(anyLikeNormalize("%a_", "foobar"));
assertTrue(anyLikeNormalize("%o_a%", "foobar"));
assertTrue(anyLikeNormalize("%i%m%", "Lorem ipsum dolor..."));
assertTrue(anyLikeNormalize("%%%sum%%", "Lorem ipsum dolor..."));
assertFalse(anyLikeNormalize("%i%m", "Lorem ipsum dolor..."));
}
@Test
public void testEvaluateStraight() throws Exception {
assertTrue(anyLike("foo", "foo", "koo", "doo"));
assertTrue(anyLike("foo", "foo"));
assertFalse(anyLike("foo"));
assertFalse(anyLike("foo", "koo", "doo"));
}
@Test
public void testEvaluateLikeMixed() {
assertTrue(anyLike("%o_ar", "foobar", "foobaz"));
assertTrue(anyLike("%a_", "foobar"));
assertTrue(anyLike("%o_a%", "foobar"));
assertTrue(anyLike("%i%m%", "Lorem ipsum dolor..."));
assertTrue(anyLike("%%%sum%%", "Lorem ipsum dolor..."));
assertFalse(anyLike("%i%m", "Lorem ipsum dolor..."));
}
@Test
public void testEvaluateNull() throws Exception {
assertNull(anyLike(null, (String) null));
assertNull(anyLike("foo", (String) null));
assertNull(anyLike(null, "bar"));
}
@Test
public void testNormalizeSymbolNull() throws Exception {
assertNull(anyLikeNormalize(null, (String) null));
assertNull(anyLikeNormalize("foo", (String) null));
assertNull(anyLikeNormalize(null, "bar"));
}
@Test
public void testNegateLike() throws Exception {
Literal patternLiteral = Literal.of("A");
Literal valuesLiteral = Literal.of(new ArrayType(DataTypes.STRING),
new Object[]{new BytesRef("A"), new BytesRef("B")});
FunctionImplementation impl = new AnyLikeOperator.AnyLikeResolver().getForTypes(
Arrays.asList(DataTypes.STRING, valuesLiteral.valueType())
);
Function anyLikeFunction = new Function(impl.info(), Arrays.<Symbol>asList(patternLiteral, valuesLiteral));
Input<Boolean> normalized = (Input<Boolean>) impl.normalizeSymbol(anyLikeFunction, new TransactionContext(SessionContext.SYSTEM_SESSION));
assertThat(normalized.value(), is(true));
assertThat(new NotPredicate().evaluate(normalized), is(false));
}
}