blob: dcc0f6ef4f995e9738c946db120558a238929da0 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.
*/
package org.apache.pinot.core.operator.transform.function;
import com.google.common.collect.Sets;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.pinot.common.function.TransformFunctionType;
import org.apache.pinot.common.request.context.ExpressionContext;
import org.apache.pinot.common.request.context.RequestContextUtils;
import org.apache.pinot.common.utils.DataSchema;
import org.apache.pinot.spi.utils.ByteArray;
import org.apache.pinot.spi.utils.BytesUtils;
import org.roaringbitmap.RoaringBitmap;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
public class InTransformFunctionTest extends BaseTransformFunctionTest {
protected int getNotInIntSV() {
Set<Integer> intSVValues = Arrays.stream(_intSVValues).boxed().collect(Collectors.toSet());
int notIn = Integer.MAX_VALUE;
while (intSVValues.contains(notIn)) {
--notIn;
}
return notIn;
}
@Test
public void testIntInTransformFunction() {
String expressionStr =
String.format("%s IN (%d, %d, %d)", INT_SV_COLUMN, _intSVValues[2], _intSVValues[5], _intSVValues[9]);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
assertTrue(transformFunction instanceof InTransformFunction);
assertEquals(transformFunction.getName(), TransformFunctionType.IN.getName());
Set<Integer> inValues = Sets.newHashSet(_intSVValues[2], _intSVValues[5], _intSVValues[9]);
int[] intValues = transformFunction.transformToIntValuesSV(_projectionBlock);
for (int i = 0; i < NUM_ROWS; i++) {
if (i == 2 || i == 5 || i == 9) {
assertEquals(intValues[i], 1);
}
assertEquals(intValues[i], inValues.contains(_intSVValues[i]) ? 1 : 0);
}
}
@Test
public void testIntNotInTransformFunction() {
String expressionStr =
String.format("%s NOT IN (%d, %d, %d)", INT_SV_COLUMN, _intSVValues[2], _intSVValues[5], _intSVValues[9]);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
assertTrue(transformFunction instanceof InTransformFunction);
assertEquals(transformFunction.getName(), TransformFunctionType.NOT_IN.getName());
Set<Integer> inValues = Sets.newHashSet(_intSVValues[2], _intSVValues[5], _intSVValues[9]);
int[] intValues = transformFunction.transformToIntValuesSV(_projectionBlock);
for (int i = 0; i < NUM_ROWS; i++) {
if (i != 2 && i != 5 && i != 9) {
assertEquals(intValues[i], 1);
}
assertEquals(intValues[i], inValues.contains(_intSVValues[i]) ? 0 : 1);
}
}
@Test
public void testIntMVInTransformFunction() {
String expressionStr =
String.format("%s IN (%d, %d, %d)", INT_MV_COLUMN, _intMVValues[2][0], _intMVValues[5][0], _intMVValues[9][0]);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
assertTrue(transformFunction instanceof InTransformFunction);
assertEquals(transformFunction.getName(), TransformFunctionType.IN.getName());
Set<Integer> inValues = Sets.newHashSet(_intMVValues[2][0], _intMVValues[5][0], _intMVValues[9][0]);
int[] intValues = transformFunction.transformToIntValuesSV(_projectionBlock);
for (int i = 0; i < NUM_ROWS; i++) {
if (i == 2 || i == 5 || i == 9) {
assertEquals(intValues[i], 1);
}
int expected = 0;
for (int intValue : _intMVValues[i]) {
if (inValues.contains(intValue)) {
expected = 1;
break;
}
}
assertEquals(intValues[i], expected);
}
}
@Test
public void testIntInTransformFunctionWithTransformedValues() {
String expressionStr = String.format("%s IN (%d, 1+1, 4+5)", INT_SV_COLUMN, _intSVValues[2]);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
assertTrue(transformFunction instanceof InTransformFunction);
assertEquals(transformFunction.getName(), TransformFunctionType.IN.getName());
Set<Integer> inValues = Sets.newHashSet(_intSVValues[2], 2, 9);
int[] intValues = transformFunction.transformToIntValuesSV(_projectionBlock);
for (int i = 0; i < NUM_ROWS; i++) {
if (i == 2) {
assertEquals(intValues[i], 1);
}
assertEquals(intValues[i], inValues.contains(_intSVValues[i]) ? 1 : 0);
}
}
@Test
public void testLongInTransformFunction() {
String expressionStr =
String.format("%s IN (%d, %d, %d)", LONG_SV_COLUMN, _longSVValues[2], _longSVValues[7], _longSVValues[11]);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
assertTrue(transformFunction instanceof InTransformFunction);
assertEquals(transformFunction.getName(), TransformFunctionType.IN.getName());
Set<Long> inValues = Sets.newHashSet(_longSVValues[2], _longSVValues[7], _longSVValues[11]);
int[] intValues = transformFunction.transformToIntValuesSV(_projectionBlock);
for (int i = 0; i < NUM_ROWS; i++) {
if (i == 2 || i == 7 || i == 11) {
assertEquals(intValues[i], 1);
}
assertEquals(intValues[i], inValues.contains(_longSVValues[i]) ? 1 : 0);
}
}
@Test
public void testFloatInTransformFunction() {
String expressionStr =
String.format("%s IN (%s, %s, %s)", FLOAT_SV_COLUMN, _floatSVValues[3], _floatSVValues[7], _floatSVValues[9]);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
assertTrue(transformFunction instanceof InTransformFunction);
assertEquals(transformFunction.getName(), TransformFunctionType.IN.getName());
Set<Float> inValues = Sets.newHashSet(_floatSVValues[3], _floatSVValues[7], _floatSVValues[9]);
int[] intValues = transformFunction.transformToIntValuesSV(_projectionBlock);
for (int i = 0; i < NUM_ROWS; i++) {
if (i == 3 || i == 7 || i == 9) {
assertEquals(intValues[i], 1);
}
assertEquals(intValues[i], inValues.contains(_floatSVValues[i]) ? 1 : 0);
}
}
@Test
public void testDoubleInTransformFunction() {
String expressionStr = String.format("%s IN (%s, %s, %s)", DOUBLE_SV_COLUMN, _doubleSVValues[3], _doubleSVValues[7],
_doubleSVValues[9]);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
assertTrue(transformFunction instanceof InTransformFunction);
assertEquals(transformFunction.getName(), TransformFunctionType.IN.getName());
Set<Double> inValues = Sets.newHashSet(_doubleSVValues[3], _doubleSVValues[7], _doubleSVValues[9]);
int[] intValues = transformFunction.transformToIntValuesSV(_projectionBlock);
for (int i = 0; i < NUM_ROWS; i++) {
if (i == 3 || i == 7 || i == 9) {
assertEquals(intValues[i], 1);
}
assertEquals(intValues[i], inValues.contains(_doubleSVValues[i]) ? 1 : 0);
}
}
@Test
public void testStringInTransformFunction() {
String expressionStr =
String.format("%s IN ('a','b','%s','%s')", STRING_SV_COLUMN, _stringSVValues[2], _stringSVValues[5]);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
assertTrue(transformFunction instanceof InTransformFunction);
assertEquals(transformFunction.getName(), TransformFunctionType.IN.getName());
Set<String> inValues = Sets.newHashSet("a", "b", _stringSVValues[2], _stringSVValues[5]);
int[] intValues = transformFunction.transformToIntValuesSV(_projectionBlock);
for (int i = 0; i < NUM_ROWS; i++) {
if (i == 2 || i == 5) {
assertEquals(intValues[i], 1);
}
assertEquals(intValues[i], inValues.contains(_stringSVValues[i]) ? 1 : 0);
}
}
@Test
public void testBytesInTransformFunction() {
String expressionStr =
String.format("%s IN ('%s','%s')", BYTES_SV_COLUMN, BytesUtils.toHexString(_bytesSVValues[2]),
BytesUtils.toHexString(_bytesSVValues[5]));
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
assertTrue(transformFunction instanceof InTransformFunction);
assertEquals(transformFunction.getName(), TransformFunctionType.IN.getName());
Set<ByteArray> inValues = Sets.newHashSet(new ByteArray(_bytesSVValues[2]), new ByteArray(_bytesSVValues[5]));
int[] intValues = transformFunction.transformToIntValuesSV(_projectionBlock);
for (int i = 0; i < NUM_ROWS; i++) {
if (i == 2 || i == 5) {
assertEquals(intValues[i], 1);
}
assertEquals(intValues[i], inValues.contains(new ByteArray(_bytesSVValues[i])) ? 1 : 0);
}
}
@Test
public void testInTransformFunctionNullLiteralReturnsNull() {
String expressionStr = String.format("%s IN (%s)", "NULL", INT_SV_NULL_COLUMN);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
int[] expectedIntValues = new int[NUM_ROWS];
RoaringBitmap expectedNullBitmap = new RoaringBitmap();
expectedNullBitmap.add((long) 0, (long) NUM_ROWS);
testTransformFunctionWithNull(transformFunction, expectedIntValues, expectedNullBitmap);
}
@Test
public void testInTransformFunctionFillsNullWithPlaceholder() {
String expressionStr = String.format("%s IN (%s)", "NULL", INT_SV_NULL_COLUMN);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
int[] expectedIntValues = new int[NUM_ROWS];
Arrays.fill(expectedIntValues, (int) DataSchema.ColumnDataType.INT.getNullPlaceholder());
assertEquals(transformFunction.transformToIntValuesSV(_projectionBlock), expectedIntValues);
}
@Test
public void testNotInTransformFunctionNullLiteralReturnsNull() {
String expressionStr = String.format("%s NOT IN (%s)", "NULL", INT_SV_NULL_COLUMN);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
int[] expectedIntValues = new int[NUM_ROWS];
RoaringBitmap expectedNullBitmap = new RoaringBitmap();
expectedNullBitmap.add((long) 0, (long) NUM_ROWS);
testTransformFunctionWithNull(transformFunction, expectedIntValues, expectedNullBitmap);
}
@Test
public void testInTransformFunctionNullIdentifierReturnsNull() {
String expressionStr = String.format("%s IN (%s)", INT_SV_NULL_COLUMN, INT_SV_COLUMN);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
int[] expectedIntValues = new int[NUM_ROWS];
RoaringBitmap expectedNullBitmap = new RoaringBitmap();
for (int i = 0; i < NUM_ROWS; i++) {
if (isNullRow(i)) {
expectedNullBitmap.add(i);
} else {
expectedIntValues[i] = 1;
}
}
testTransformFunctionWithNull(transformFunction, expectedIntValues, expectedNullBitmap);
}
@Test
public void testInTransformFunctionLiteralNotInValuesThatContainNullReturnsNull() {
String expressionStr = String.format("%s IN (%s)", getNotInIntSV(), INT_SV_NULL_COLUMN);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
int[] expectedIntValues = new int[NUM_ROWS];
RoaringBitmap expectedNullBitmap = new RoaringBitmap();
for (int i = 0; i < NUM_ROWS; i++) {
if (isNullRow(i)) {
expectedNullBitmap.add(i);
} else {
expectedIntValues[i] = 0;
}
}
testTransformFunctionWithNull(transformFunction, expectedIntValues, expectedNullBitmap);
}
@Test
public void testNotInTransformFunctionLiteralNotInValuesThatContainNullReturnsNull() {
String expressionStr = String.format("%s NOT IN (%s)", getNotInIntSV(), INT_SV_NULL_COLUMN);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
int[] expectedIntValues = new int[NUM_ROWS];
RoaringBitmap expectedNullBitmap = new RoaringBitmap();
for (int i = 0; i < NUM_ROWS; i++) {
if (isNullRow(i)) {
expectedNullBitmap.add(i);
} else {
expectedIntValues[i] = 1;
}
}
testTransformFunctionWithNull(transformFunction, expectedIntValues, expectedNullBitmap);
}
@Test
public void testInTransformFunctionIdentifierInValuesThatContainNullReturnsTrue() {
String expressionStr = String.format("%s IN (%s, %s)", INT_SV_COLUMN, INT_SV_COLUMN, INT_SV_NULL_COLUMN);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
int[] expectedIntValues = new int[NUM_ROWS];
Arrays.fill(expectedIntValues, 1);
RoaringBitmap expectedNullBitmap = new RoaringBitmap();
testTransformFunctionWithNull(transformFunction, expectedIntValues, expectedNullBitmap);
}
@Test
public void testInTransformFunctionIdentifierInAllLiteralValuesThatContainNullReturnsTrue() {
String expressionStr = String.format("%s IN (%s, %s, null)", INT_SV_COLUMN, _intSVValues[0], _intSVValues[0] + 1);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
Pair<int[], RoaringBitmap> intValuesWithNull = transformFunction.transformToIntValuesSVWithNull(_projectionBlock);
assertEquals(intValuesWithNull.getLeft()[0], 1);
assertFalse(intValuesWithNull.getRight().contains(0));
}
@Test
public void testInTransformFunctionIdentifierNotInAllLiteralValuesThatContainNullReturnsNull() {
String expressionStr =
String.format("%s IN (%s, %s, NULL)", INT_SV_COLUMN, _intSVValues[0] + 1, _intSVValues[0] + 2);
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
assertTrue(transformFunction.transformToIntValuesSVWithNull(_projectionBlock).getRight().contains(0));
}
@Test
public void testInTransformFunctionLiteralInAllLiteralValuesThatContainNullReturnsTrue() {
String expressionStr = "1 IN (1, 2, NULL)";
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
int[] expectedIntValues = new int[NUM_ROWS];
Arrays.fill(expectedIntValues, 1);
RoaringBitmap expectedNullBitmap = new RoaringBitmap();
testTransformFunctionWithNull(transformFunction, expectedIntValues, expectedNullBitmap);
}
@Test
public void testInTransformFunctionLiteralNullAndAllLiteralValuesReturnsNull() {
String expressionStr = "NULL IN (1, 2, 3)";
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
RoaringBitmap expectedNullBitmap = new RoaringBitmap();
expectedNullBitmap.add((long) 0, (long) NUM_ROWS);
assertEquals(transformFunction.transformToIntValuesSVWithNull(_projectionBlock).getRight(), expectedNullBitmap);
}
@Test
public void testInTransformFunctionLiteralNotInAllLiteralValuesThatContainNullReturnsNull() {
String expressionStr = "1 IN (2, 3, NULL)";
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
RoaringBitmap expectedNullBitmap = new RoaringBitmap();
expectedNullBitmap.add((long) 0, (long) NUM_ROWS);
assertEquals(transformFunction.transformToIntValuesSVWithNull(_projectionBlock).getRight(), expectedNullBitmap);
}
@Test
public void testNotInTransformFunctionLiteralNotInAllLiteralValuesThatContainNullReturnsNull() {
String expressionStr = "1 NOT IN (2, 3, NULL)";
ExpressionContext expression = RequestContextUtils.getExpression(expressionStr);
TransformFunction transformFunction = TransformFunctionFactory.get(expression, _dataSourceMap);
RoaringBitmap expectedNullBitmap = new RoaringBitmap();
expectedNullBitmap.add((long) 0, (long) NUM_ROWS);
assertEquals(transformFunction.transformToIntValuesSVWithNull(_projectionBlock).getRight(), expectedNullBitmap);
}
}