/* * 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 AnyNotLikeOperatorTest 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); AnyNotLikeOperator impl = (AnyNotLikeOperator) new AnyNotLikeOperator.AnyNotLikeResolver().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 anyNotLikeNormalize(String pattern, String... expressions) { return (Boolean) ((Literal) normalizeSymbol(pattern, expressions)).value(); } private Boolean anyNotLike(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); AnyNotLikeOperator impl = (AnyNotLikeOperator) new AnyNotLikeOperator.AnyNotLikeResolver().getForTypes( Arrays.asList(DataTypes.STRING, valuesLiteral.valueType()) ); return impl.evaluate(patternLiteral, valuesLiteral); } @Test public void testNormalizeSingleSymbolEqual() { assertFalse(anyNotLikeNormalize("foo", "foo")); assertTrue(anyNotLikeNormalize("notFoo", "foo")); } @Test public void testNormalizeSymbolLikeZeroOrMore() { // Following tests: wildcard: '%' ... zero or more characters (0...N) assertFalse(anyNotLikeNormalize("%bar", "foobar", "bar")); assertFalse(anyNotLikeNormalize("%bar", "bar")); assertTrue(anyNotLikeNormalize("%bar", "ar", "car")); assertTrue(anyNotLikeNormalize("foo%", "foobar", "kuhbar")); assertTrue(anyNotLikeNormalize("foo%", "foo", "kuh")); assertTrue(anyNotLikeNormalize("foo%", "fo", "kuh")); assertFalse(anyNotLikeNormalize("%oob%", "foobar")); } @Test public void testNormalizeSymbolLikeExactlyOne() { // Following tests: wildcard: '_' ... any single character (exactly one) assertFalse(anyNotLikeNormalize("_ar", "bar")); assertTrue(anyNotLikeNormalize("_bar", "bar")); assertFalse(anyNotLikeNormalize("fo_", "foo", "for")); assertTrue(anyNotLikeNormalize("foo_", "foo", "foot")); assertTrue(anyNotLikeNormalize("foo_", "foo")); assertFalse(anyNotLikeNormalize("_o_", "foo")); assertTrue(anyNotLikeNormalize("_foobar_", "foobar")); } // Following tests: mixed wildcards: @Test public void testNormalizeSymbolLikeMixed() { assertTrue(anyNotLikeNormalize("%o_ar", "foobar", "foobaz")); assertFalse(anyNotLikeNormalize("%a_", "foobar")); assertFalse(anyNotLikeNormalize("%o_a%", "foobar")); assertFalse(anyNotLikeNormalize("%i%m%", "Lorem ipsum dolor...")); assertFalse(anyNotLikeNormalize("%%%sum%%", "Lorem ipsum dolor...")); assertTrue(anyNotLikeNormalize("%i%m", "Lorem ipsum dolor...")); } @Test public void testEvaluateStraight() throws Exception { assertTrue(anyNotLike("foo", "foo", "koo", "doo")); assertFalse(anyNotLike("foo", "foo")); assertFalse(anyNotLike("foo")); assertTrue(anyNotLike("foo", "koo", "doo")); } @Test public void testEvaluateLikeMixed() { assertTrue(anyNotLike("%o_ar", "foobar", "foobaz")); assertFalse(anyNotLike("%a_", "foobar")); assertFalse(anyNotLike("%o_a%", "foobar")); assertFalse(anyNotLike("%i%m%", "Lorem ipsum dolor...")); assertFalse(anyNotLike("%%%sum%%", "Lorem ipsum dolor...")); assertTrue(anyNotLike("%i%m", "Lorem ipsum dolor...")); } @Test public void testEvaluateNull() throws Exception { assertNull(anyNotLike(null, (String) null)); assertNull(anyNotLike("foo", (String) null)); assertNull(anyNotLike(null, "bar")); } @Test public void testNormalizeSymbolNull() throws Exception { assertNull(anyNotLikeNormalize(null, (String) null)); assertNull(anyNotLikeNormalize("foo", (String) null)); assertNull(anyNotLikeNormalize(null, "bar")); } @Test public void testNegateNotLike() 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 AnyNotLikeOperator.AnyNotLikeResolver().getForTypes( Arrays.asList(DataTypes.STRING, valuesLiteral.valueType()) ); Function anyNotLikeFunction = new Function(impl.info(), Arrays.<Symbol>asList(patternLiteral, valuesLiteral)); Input<Boolean> normalized = (Input<Boolean>) impl.normalizeSymbol(anyNotLikeFunction, new TransactionContext(SessionContext.SYSTEM_SESSION)); assertThat(normalized.value(), is(true)); assertThat(new NotPredicate().evaluate(normalized), is(false)); } }