Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
1887f9f
initial cherry-pick
nishantmonu51 Feb 26, 2018
51be891
review comment - aggregator method naming, avoid using Pair
nishantmonu51 Feb 26, 2018
f1f655e
More fixes
nishantmonu51 Feb 26, 2018
92b8451
druid-sql Null Handling
nishantmonu51 Feb 28, 2018
fd570b3
fix test
nishantmonu51 Feb 28, 2018
14a8148
enable more tests
nishantmonu51 Feb 28, 2018
ced5c24
Fix ExpressionFilterTest
nishantmonu51 Feb 28, 2018
a5b6f9b
fix tests
nishantmonu51 Mar 1, 2018
97f6114
revert unintentional change
nishantmonu51 Mar 2, 2018
351aefb
review comments
nishantmonu51 Mar 15, 2018
a7418d7
Merge remote-tracking branch 'upstream/master' into null-handling-pr-2
nishantmonu51 Mar 15, 2018
15000cb
review comments
nishantmonu51 Mar 15, 2018
8ae2c97
review comment - cache numeric val in StringExprEval
nishantmonu51 Mar 15, 2018
6c81208
fix checkstyle
nishantmonu51 Mar 16, 2018
c35c14d
Merge remote-tracking branch 'upstream/master' into null-handling-pr-2
nishantmonu51 Mar 28, 2018
d23956d
fix compilation
nishantmonu51 Mar 28, 2018
d4f9b89
review comments
nishantmonu51 Apr 9, 2018
bd5f108
Merge remote-tracking branch 'upstream/master' into null-handling-pr-2
nishantmonu51 Apr 9, 2018
ddae594
review comments
nishantmonu51 Apr 10, 2018
c20c930
review comment
nishantmonu51 Apr 10, 2018
a83c933
review comments and make lookup null handling consistent
nishantmonu51 Apr 10, 2018
c22c43a
more review comments and unit test fixes
nishantmonu51 Apr 10, 2018
b095f45
set default useDefaultValuesForNull to true
nishantmonu51 Apr 12, 2018
eddd435
fix checkstyle
nishantmonu51 Apr 12, 2018
8bc95aa
revert unwanted change
nishantmonu51 Apr 12, 2018
04199c3
fix comment
nishantmonu51 Apr 12, 2018
fe17eb8
More Review comments and test fixes
nishantmonu51 Apr 13, 2018
a7c88a9
cosmetic changes
nishantmonu51 Apr 13, 2018
2b7ebdf
Fix travis ci and intellij inspections
nishantmonu51 Apr 23, 2018
e88db45
handle intellij code inspection failure
nishantmonu51 Apr 24, 2018
86270e4
Fix backwards compatibility when parsing origin from empty string for…
nishantmonu51 May 8, 2018
3ef44ac
Merge remote-tracking branch 'upstream/master' into null-handling-pr-2
nishantmonu51 May 8, 2018
0281185
review comments and fix test failures from master merge
nishantmonu51 May 9, 2018
a909829
Merge remote-tracking branch 'upstream/master' into null-handling-pr-2
nishantmonu51 May 10, 2018
ad204a9
remove unnecessary nullToEmpty
nishantmonu51 May 10, 2018
0fdecc4
More fixes to Druid Expressions found during testing
nishantmonu51 May 18, 2018
06078ec
Merge remote-tracking branch 'remotes/upstream/master' into null-hand…
nishantmonu51 May 22, 2018
78e3b08
review comments - Extract out null handling for GroupBySerdeHelpers
nishantmonu51 May 22, 2018
a9e9179
Extract NullableGroupBycolumnSelectorStrategy, Null Bytes fix failing…
nishantmonu51 May 22, 2018
4f1f2ca
review comments
nishantmonu51 May 29, 2018
1c081f4
review comments
nishantmonu51 Jun 8, 2018
d9c557d
Merge remote-tracking branch 'remotes/upstream/master' into null-hand…
nishantmonu51 Jun 8, 2018
d2c0084
Merge remote-tracking branch 'remotes/upstream/master' into null-hand…
nishantmonu51 Jun 16, 2018
00e14b7
review comments
nishantmonu51 Jun 18, 2018
ef0e725
Review comments
nishantmonu51 Jun 22, 2018
fc3b129
Merge remote-tracking branch 'remotes/upstream/master' into null-hand…
nishantmonu51 Jun 22, 2018
cd8b124
add comments to code
nishantmonu51 Jun 23, 2018
983af33
Merge remote-tracking branch 'upstream/master' into null-handling-pr-2
nishantmonu51 Jun 30, 2018
7074b69
review comments
nishantmonu51 Jul 6, 2018
cc0066d
Merge remote-tracking branch 'upstream/master' into null-handling-pr-2
nishantmonu51 Jul 6, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ matrix:
- unset _JAVA_OPTIONS
script: echo "MAVEN_OPTS='-Xmx512m'" > ~/.mavenrc && mvn test -B -Pparallel-test -Dmaven.fork.count=2 -pl processing

# processing module tests with SQL Compatibility enabled
- sudo: false
env:
- NAME="processing module test with SQL Compatibility"
install: echo "MAVEN_OPTS='-Xmx3000m'" > ~/.mavenrc && mvn install -q -ff -DskipTests -B
before_script:
- unset _JAVA_OPTIONS
script: echo "MAVEN_OPTS='-Xmx512m'" > ~/.mavenrc && mvn test -B -Pparallel-test -Dmaven.fork.count=2 -Ddruid.generic.useDefaultValueForNull=false -pl processing

# server module test
- sudo: false
env:
Expand All @@ -43,6 +52,17 @@ matrix:
# Server module test is run without the parallel-test option because it's memory sensitive and often fails with that option.
script: echo "MAVEN_OPTS='-Xmx512m'" > ~/.mavenrc && mvn test -B -pl server

# server module test with SQL Compatibility enabled
- sudo: false
env:
- NAME="server module test with SQL Compatibility enabled"
install: echo "MAVEN_OPTS='-Xmx3000m'" > ~/.mavenrc && mvn install -q -ff -DskipTests -B
before_script:
- unset _JAVA_OPTIONS
# Server module test is run without the parallel-test option because it's memory sensitive and often fails with that option.
script: echo "MAVEN_OPTS='-Xmx512m'" > ~/.mavenrc && mvn test -B -pl server -Ddruid.generic.useDefaultValueForNull=false


# other modules test
- sudo: false
env:
Expand All @@ -53,6 +73,16 @@ matrix:
- unset _JAVA_OPTIONS
script: echo "MAVEN_OPTS='-Xmx512m'" > ~/.mavenrc && mvn test -B -Pparallel-test -Dmaven.fork.count=2 -pl '!processing,!server'

# other modules test with SQL Compatibility enabled
- sudo: false
env:
- NAME="other modules test with SQL Compatibility"
- AWS_REGION=us-east-1 # set a aws region for unit tests
install: echo "MAVEN_OPTS='-Xmx3000m'" > ~/.mavenrc && mvn install -q -ff -DskipTests -B
before_script:
- unset _JAVA_OPTIONS
script: echo "MAVEN_OPTS='-Xmx512m'" > ~/.mavenrc && mvn test -B -Pparallel-test -Dmaven.fork.count=2 -Ddruid.generic.useDefaultValueForNull=false -pl '!processing,!server'

# run integration tests
- sudo: required
services:
Expand Down
5 changes: 4 additions & 1 deletion api/src/main/java/io/druid/data/input/Rows.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Maps;
import com.google.common.primitives.Longs;
import io.druid.common.config.NullHandling;
import io.druid.java.util.common.StringUtils;
import io.druid.java.util.common.parsers.ParseException;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -92,10 +94,11 @@ public static List<String> objectToStrings(final Object inputValue)
* @throws NullPointerException if the string is null
* @throws ParseException if the column cannot be converted to a number
*/
@Nullable
public static Number objectToNumber(final String name, final Object inputValue)
{
if (inputValue == null) {
return Rows.LONG_ZERO;
return NullHandling.defaultLongValue();
}

if (inputValue instanceof Number) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
import io.druid.benchmark.datagen.BenchmarkDataGenerator;
import io.druid.benchmark.datagen.BenchmarkSchemaInfo;
import io.druid.benchmark.datagen.BenchmarkSchemas;
import io.druid.common.config.NullHandling;
import io.druid.data.input.InputRow;
import io.druid.hll.HyperLogLogHash;
import io.druid.jackson.DefaultObjectMapper;
Expand Down Expand Up @@ -557,7 +557,7 @@ public Filter toFilter()
if (extractionFn == null) {
return new NoBitmapSelectorFilter(dimension, value);
} else {
final String valueOrNull = Strings.emptyToNull(value);
final String valueOrNull = NullHandling.emptyToNullIfNeeded(value);

final DruidPredicateFactory predicateFactory = new DruidPredicateFactory()
{
Expand Down
10 changes: 10 additions & 0 deletions codestyle/checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -171,5 +171,15 @@
<property name="illegalPattern" value="true"/>
<property name="message" value="Use java.lang.Primitive.BYTES instead."/>
</module>
<module name="Regexp">
<property name="format" value="Strings.emptyToNull"/>
<property name="illegalPattern" value="true"/>
<property name="message" value="Use io.druid.common.config.NullHandling.emptyToNullIfNeeded instead"/>
</module>
<module name="Regexp">
<property name="format" value="Strings.nullToEmpty"/>
<property name="illegalPattern" value="true"/>
<property name="message" value="Use io.druid.common.config.NullHandling.nullToEmptyIfNeeded instead"/>
</module>
</module>
</module>
4 changes: 2 additions & 2 deletions common/src/main/java/io/druid/math/expr/Evals.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

package io.druid.math.expr;

import com.google.common.base.Strings;
import io.druid.common.config.NullHandling;
import io.druid.java.util.common.logger.Logger;

import java.util.Arrays;
Expand Down Expand Up @@ -83,6 +83,6 @@ public static boolean asBoolean(double x)

public static boolean asBoolean(String x)
{
return !Strings.isNullOrEmpty(x) && Boolean.valueOf(x);
return !NullHandling.isNullOrEquivalent(x) && Boolean.valueOf(x);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you implement this thing: #5278 (comment) in this PR?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, will add a checkstyle rule.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added.

}
}
14 changes: 13 additions & 1 deletion common/src/main/java/io/druid/math/expr/Expr.java
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ class UnaryMinusExpr extends UnaryExpr
public ExprEval eval(ObjectBinding bindings)
{
ExprEval ret = expr.eval(bindings);
if (NullHandling.sqlCompatible() && (ret.value() == null)) {
return ExprEval.of(null);
}
if (ret.type() == ExprType.LONG) {
return ExprEval.of(-ret.asLong());
}
Expand Down Expand Up @@ -307,6 +310,9 @@ class UnaryNotExpr extends UnaryExpr
public ExprEval eval(ObjectBinding bindings)
{
ExprEval ret = expr.eval(bindings);
if (NullHandling.sqlCompatible() && (ret.value() == null)) {
return ExprEval.of(null);
}
// conforming to other boolean-returning binary operators
ExprType retType = ret.type() == ExprType.DOUBLE ? ExprType.DOUBLE : ExprType.LONG;
return ExprEval.of(!ret.asBoolean(), retType);
Expand Down Expand Up @@ -365,15 +371,21 @@ public ExprEval eval(ObjectBinding bindings)

// Result of any Binary expressions is null if any of the argument is null.
// e.g "select null * 2 as c;" or "select null + 1 as c;" will return null as per Standard SQL spec.
if (NullHandling.sqlCompatible() && (leftVal.isNull() || rightVal.isNull())) {
if (NullHandling.sqlCompatible() && (leftVal.value() == null || rightVal.value() == null)) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason is that for String ExprEval isNull method now checks that the expression can be parsed as a valid long/double/float or not instead of checking the nullability.
Have added a comment on the ExprEval isNull method that explains this change.

return ExprEval.of(null);
}

if (leftVal.type() == ExprType.STRING && rightVal.type() == ExprType.STRING) {
return evalString(leftVal.asString(), rightVal.asString());
} else if (leftVal.type() == ExprType.LONG && rightVal.type() == ExprType.LONG) {
if (NullHandling.sqlCompatible() && (leftVal.isNumericNull() || rightVal.isNumericNull())) {
return ExprEval.of(null);
}
return ExprEval.of(evalLong(leftVal.asLong(), rightVal.asLong()));
} else {
if (NullHandling.sqlCompatible() && (leftVal.isNumericNull() || rightVal.isNumericNull())) {
return ExprEval.of(null);
}
return ExprEval.of(evalDouble(leftVal.asDouble(), rightVal.asDouble()));
}
}
Expand Down
98 changes: 66 additions & 32 deletions common/src/main/java/io/druid/math/expr/ExprEval.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@

package io.druid.math.expr;

import com.google.common.base.Preconditions;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Ints;
import io.druid.common.config.NullHandling;
import io.druid.common.guava.GuavaUtils;
import io.druid.java.util.common.IAE;
Expand All @@ -32,7 +30,7 @@
*/
public abstract class ExprEval<T>
{
public static ExprEval ofLong(Number longValue)
public static ExprEval ofLong(@Nullable Number longValue)
{
return new LongExprEval(longValue);
}
Expand All @@ -42,7 +40,7 @@ public static ExprEval of(long longValue)
return new LongExprEval(longValue);
}

public static ExprEval ofDouble(Number doubleValue)
public static ExprEval ofDouble(@Nullable Number doubleValue)
{
return new DoubleExprEval(doubleValue);
}
Expand Down Expand Up @@ -71,7 +69,7 @@ public static ExprEval of(boolean value, ExprType type)
}
}

public static ExprEval bestEffortOf(Object val)
public static ExprEval bestEffortOf(@Nullable Object val)
{
if (val instanceof ExprEval) {
return (ExprEval) val;
Expand All @@ -85,6 +83,7 @@ public static ExprEval bestEffortOf(Object val)
return new StringExprEval(val == null ? null : String.valueOf(val));
}

@Nullable
final T value;

private ExprEval(T value)
Expand All @@ -99,10 +98,10 @@ public Object value()
return value;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field should be annotated @Nullable.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

}

public boolean isNull()
{
return value == null;
}
/**
* returns true if numeric primitive value for this ExprEval is null, otherwise false.
*/
public abstract boolean isNumericNull();

public abstract int asInt();

Expand All @@ -125,7 +124,7 @@ public String asString()
private abstract static class NumericExprEval extends ExprEval<Number>
{

private NumericExprEval(Number value)
private NumericExprEval(@Nullable Number value)
{
super(value);
}
Expand All @@ -147,13 +146,19 @@ public final double asDouble()
{
return value.doubleValue();
}

@Override
public boolean isNumericNull()
{
return value == null;
}
}

private static class DoubleExprEval extends NumericExprEval
{
private DoubleExprEval(Number value)
private DoubleExprEval(@Nullable Number value)
{
super(Preconditions.checkNotNull(value, "value"));
super(value == null ? NullHandling.defaultDoubleValue() : value);
}

@Override
Expand All @@ -175,7 +180,7 @@ public final ExprEval castTo(ExprType castTo)
case DOUBLE:
return this;
case LONG:
return ExprEval.of(asLong());
return ExprEval.of(value == null ? null : asLong());
case STRING:
return ExprEval.of(asString());
}
Expand All @@ -191,9 +196,9 @@ public Expr toExpr()

private static class LongExprEval extends NumericExprEval
{
private LongExprEval(Number value)
private LongExprEval(@Nullable Number value)
{
super(Preconditions.checkNotNull(value, "value"));
super(value == null ? NullHandling.defaultLongValue() : value);
}

@Override
Expand All @@ -213,7 +218,7 @@ public final ExprEval castTo(ExprType castTo)
{
switch (castTo) {
case DOUBLE:
return ExprEval.of(asDouble());
return ExprEval.of(value == null ? null : asDouble());
case LONG:
return this;
case STRING:
Expand All @@ -231,6 +236,8 @@ public Expr toExpr()

private static class StringExprEval extends ExprEval<String>
{
private Number numericVal;

private StringExprEval(@Nullable String value)
{
super(NullHandling.emptyToNullIfNeeded(value));
Expand All @@ -245,36 +252,63 @@ public final ExprType type()
@Override
public final int asInt()
{
if (value == null) {
Number number = asNumber();
if (number == null) {
assert NullHandling.replaceWithDefault();
return 0;
}

final Integer theInt = Ints.tryParse(value);
assert NullHandling.replaceWithDefault() || theInt != null;
return theInt == null ? 0 : theInt;
return number.intValue();
}

@Override
public final long asLong()
{
// GuavaUtils.tryParseLong handles nulls, no need for special null handling here.
final Long theLong = GuavaUtils.tryParseLong(value);
assert NullHandling.replaceWithDefault() || theLong != null;
return theLong == null ? 0L : theLong;
Number number = asNumber();
if (number == null) {
assert NullHandling.replaceWithDefault();
return 0L;
}
return number.longValue();
}

@Override
public final double asDouble()
{
if (value == null) {
Number number = asNumber();
if (number == null) {
assert NullHandling.replaceWithDefault();
return 0.0;
return 0.0d;
}
return number.doubleValue();
}

@Nullable
private Number asNumber()
{
if (value == null) {
return null;
}
if (numericVal != null) {
// Optimization for non-null case.
return numericVal;
}
Number rv;
Long v = GuavaUtils.tryParseLong(value);
// Do NOT use ternary operator here, because it makes Java to convert Long to Double
if (v != null) {
rv = v;
} else {
rv = Doubles.tryParse(value);
}

numericVal = rv;
return rv;
}

final Double theDouble = Doubles.tryParse(value);
assert NullHandling.replaceWithDefault() || theDouble != null;
return theDouble == null ? 0.0 : theDouble;
@Override
public boolean isNumericNull()
{
return asNumber() == null;
}

@Override
Expand All @@ -288,9 +322,9 @@ public final ExprEval castTo(ExprType castTo)
{
switch (castTo) {
case DOUBLE:
return ExprEval.of(asDouble());
return ExprEval.ofDouble(asNumber());
case LONG:
return ExprEval.of(asLong());
return ExprEval.ofLong(asNumber());
case STRING:
return this;
}
Expand Down
Loading