/*
* Licensed to 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.scalar.conditional;
import com.google.common.collect.ImmutableList;
import io.crate.analyze.symbol.Literal;
import io.crate.operation.scalar.AbstractScalarFunctionsTest;
import io.crate.types.DataType;
import io.crate.types.DataTypes;
import org.junit.Test;
import java.util.Collections;
public class ConditionalFunctionTest extends AbstractScalarFunctionsTest {
@Test
public void testArgsLength() throws Exception {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("dummy function requires at least one argument");
ConditionalFunction.createInfo("dummy", Collections.<DataType>emptyList());
}
@Test
public void testInvalidDataType() throws Exception {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("all arguments for dummy function must have the same data type");
ConditionalFunction.createInfo("dummy",
ImmutableList.<DataType>of(DataTypes.STRING, DataTypes.INTEGER));
}
@Test
public void testCoalesce() throws Exception {
assertEvaluate("coalesce(null)", null);
assertEvaluate("coalesce(10, null, 20)", 10L);
assertEvaluate("coalesce(name, 'foo')", "foo", Literal.NULL);
}
@Test
public void testGreatest() throws Exception {
assertEvaluate("greatest(null, null)", null);
assertEvaluate("greatest(10)", 10L);
assertEvaluate("greatest(10, 20, null, 30)", 30L);
assertEvaluate("greatest(11.1, 22.2, null)", 22.2);
assertEvaluate("greatest('foo', name, 'bar')", "foo", Literal.NULL);
}
@Test
public void testLeast() throws Exception {
assertEvaluate("least(null, null)", null);
assertEvaluate("least(10)", 10L);
assertEvaluate("least(10, 20, null, 30)", 10L);
assertEvaluate("least(11.1, 22.2, null)", 11.1);
assertEvaluate("least('foo', name, 'bar')", "bar", Literal.NULL);
}
@Test
public void testNullIf() throws Exception {
assertEvaluate("nullif(10, 12)", 10L);
assertEvaluate("nullif(name, 'foo')", null, Literal.of("foo"));
assertEvaluate("nullif(null, 'foo')", null);
}
@Test
public void testNullIfInvalidArgsLength() throws Exception {
expectedException.expect(UnsupportedOperationException.class);
expectedException.expectMessage("unknown function: nullif(long, long, long)");
assertEvaluate("nullif(1, 2, 3)", null);
}
@Test
public void testCase() throws Exception {
assertEvaluate("case name when 'foo' then 'hello foo' when 'bar' then 'hello bar' end",
"hello foo",
Literal.of("foo"), Literal.of("foo"));
assertEvaluate("case name when 'foo' then 'hello foo' when 'bar' then 'hello bar' else 'hello stranger' end",
"hello stranger",
Literal.of("hoschi"), Literal.of("hoschi"));
assertEvaluate("case when name = 'foo' then 'hello foo' when name = 'bar' then 'hello bar' end",
"hello foo",
Literal.of("foo"), Literal.of("foo"));
assertEvaluate("case when name = 'foo' then 'hello foo' when name = 'bar' then 'hello bar' else 'hello stranger' end",
"hello stranger",
Literal.of("hoschi"), Literal.of("hoschi"));
// test that result expression is only evaluated if the condition is true
assertEvaluate("case when id != 0 then 10/id > 1.5 else false end",
false,
Literal.of(0), Literal.of(0));
// testing nested case statements
assertEvaluate("case when id != 0 then case when id = 1 then true end else false end",
true,
Literal.of(1), Literal.of(1));
}
@Test
public void testCaseIncompatibleTypes() throws Exception {
expectedException.expect(UnsupportedOperationException.class);
expectedException.expectMessage("Data types of all result expressions of a CASE statement must be equal, " +
"found: [string, long]");
assertEvaluate("case name when 'foo' then 'hello foo' when 'bar' then 1 end",
"hello foo",
Literal.of("foo"), Literal.of("foo"));
}
@Test
public void testIf() throws Exception {
assertEvaluate("if(id = 0, 'zero', 'other')", "zero", Literal.of(0), Literal.of(0));
assertEvaluate("if(id = 0, 'zero', if(id = 1, 'one', 'other'))", "one", Literal.of(1), Literal.of(1));
}
@Test
public void testCaseWithDifferentOperandTypes() throws Exception {
// x = long
// a = integer
String expression = "case x + 1 when a then 111 end";
assertEvaluate(expression, 111L,
Literal.of(110L), // x
Literal.of(111)); // a
}
}