Skip to content

Commit 9553187

Browse files
committed
exception tree
1 parent b31597a commit 9553187

21 files changed

+461
-161
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package io.whitefox.core;
2+
3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import com.fasterxml.jackson.databind.module.SimpleModule;
6+
import io.whitefox.core.types.DataType;
7+
import io.whitefox.core.types.predicates.DataTypeDeserializer;
8+
9+
10+
public class DeltaObjectMapper {
11+
12+
private static final ObjectMapper objectMapper = newInstance();
13+
14+
private static ObjectMapper newInstance() {
15+
ObjectMapper mapper = new ObjectMapper();
16+
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
17+
var customSerializersModule = new SimpleModule();
18+
customSerializersModule.addDeserializer(DataType.class, new DataTypeDeserializer());
19+
mapper.registerModule(customSerializersModule);
20+
return mapper;
21+
}
22+
23+
public static ObjectMapper getInstance() {
24+
return objectMapper;
25+
}
26+
}

server/core/src/main/java/io/whitefox/core/JsonPredicatesUtils.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,29 @@
66
import io.whitefox.core.types.predicates.BaseOp;
77
import io.whitefox.core.types.predicates.EvalContext;
88
import java.util.Map;
9+
10+
import io.whitefox.core.types.predicates.PredicateParsingException;
911
import org.apache.commons.lang3.tuple.Pair;
1012

1113
public class JsonPredicatesUtils {
1214

13-
public static BaseOp parsePredicate(String predicate) throws JsonProcessingException {
14-
var mapper = new ObjectMapper();
15-
return mapper.readValue(predicate, BaseOp.class);
15+
private static final ObjectMapper objectMapper = DeltaObjectMapper.getInstance();
16+
17+
public static BaseOp parsePredicate(String predicate) throws PredicateParsingException {
18+
try {
19+
return objectMapper.readValue(predicate, BaseOp.class);
20+
}
21+
catch (JsonProcessingException e){
22+
throw new PredicateParsingException(e);
23+
}
1624
}
1725

1826
public static EvalContext createEvalContext(AddFile file) {
1927
var statsString = file.getStats();
2028
var partitionValues = file.getPartitionValues();
2129

22-
var mapper = new ObjectMapper();
2330
try {
24-
var fileStats = mapper.readValue(statsString, FileStats.class);
31+
var fileStats = objectMapper.readValue(statsString, FileStats.class);
2532
var maxValues = fileStats.maxValues;
2633
var mappedMinMaxPairs = new java.util.HashMap<String, Pair<String, String>>();
2734
fileStats.getMinValues().forEach((minK, minV) -> {
@@ -31,6 +38,8 @@ public static EvalContext createEvalContext(AddFile file) {
3138
});
3239
return new EvalContext(partitionValues, mappedMinMaxPairs);
3340
} catch (JsonProcessingException e) {
41+
42+
// TODO handle like PredicateParsingException
3443
var message = e.getMessage();
3544
return new EvalContext(partitionValues, Map.of());
3645
}

server/core/src/main/java/io/whitefox/core/services/DeltaSharedTable.java

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
import io.whitefox.core.*;
99
import io.whitefox.core.Metadata;
1010
import io.whitefox.core.TableSchema;
11-
import io.whitefox.core.types.predicates.BaseOp;
11+
import io.whitefox.core.types.predicates.PredicateException;
12+
import io.whitefox.core.types.predicates.TypeNotSupportedException;
13+
import jakarta.inject.Inject;
14+
1215
import java.sql.Timestamp;
1316
import java.time.OffsetDateTime;
1417
import java.time.format.DateTimeFormatter;
1518
import java.util.List;
1619
import java.util.Optional;
1720
import java.util.stream.Collectors;
18-
import io.whitefox.core.types.predicates.BaseOp;
19-
import org.apache.hadoop.conf.Configuration;
2021

2122
public class DeltaSharedTable {
22-
2323
private final DeltaLog deltaLog;
2424
private final TableSchemaConverter tableSchemaConverter;
2525
private final SharedTable tableDetails;
@@ -87,17 +87,8 @@ public Optional<Long> getTableVersion(Optional<String> startingTimestamp) {
8787
return getSnapshot(startingTimestamp).map(Snapshot::getVersion);
8888
}
8989

90-
public static BaseOp parsePredicate(String predicate) throws JsonProcessingException {
91-
ObjectMapper mapper = new ObjectMapper();
92-
try {
93-
return mapper.readValue(predicate, BaseOp.class);
94-
} catch (JsonProcessingException e) {
95-
System.out.println("cant parse predicate");
96-
throw e;
97-
}
98-
}
99-
100-
public boolean filterFileBasedOnPredicates(List<String> predicates, AddFile f) {
90+
public boolean filterFilesBasedOnPredicates(List<String> predicates, AddFile f) {
91+
// if there are no predicates return all possible files
10192
if (predicates == null) {
10293
return true;
10394
}
@@ -106,9 +97,10 @@ public boolean filterFileBasedOnPredicates(List<String> predicates, AddFile f) {
10697
try {
10798
var parsedPredicate = JsonPredicatesUtils.parsePredicate(p);
10899
return parsedPredicate.evalExpectBoolean(ctx);
109-
} catch (JsonProcessingException e) {
110-
System.out.println("Unable to parse predicate: " + p + " due to: " + e);
111-
return false;
100+
} catch (PredicateException e) {
101+
System.out.println("Caught exception: " + e.getMessage());
102+
System.out.println("File: " + f.getPath() + " will be used in processing due to failure in parsing or processing the predicate");
103+
return true;
112104
}
113105
});
114106
}
@@ -134,7 +126,7 @@ public ReadTableResultToBeSigned queryTable(ReadTableRequest readTableRequest) {
134126
new Protocol(Optional.of(1)),
135127
metadataFromSnapshot(snapshot),
136128
snapshot.getAllFiles().stream()
137-
.filter(f -> filterFileBasedOnPredicates(predicates, f))
129+
.filter(f -> filterFilesBasedOnPredicates(predicates, f))
138130
.map(f -> new TableFileToBeSigned(
139131
location() + "/" + f.getPath(),
140132
f.getSize(),

server/core/src/main/java/io/whitefox/core/types/predicates/BaseOp.java

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.fasterxml.jackson.annotation.JsonSubTypes;
44
import com.fasterxml.jackson.annotation.JsonTypeInfo;
55
import io.whitefox.core.types.*;
6+
67
import java.util.List;
78
import java.util.Objects;
89

@@ -22,31 +23,34 @@
2223
})
2324
public interface BaseOp {
2425

25-
void validate();
26+
void validate() throws PredicateException;
2627

27-
default Boolean isSupportedType(DataType valueType, Boolean forV2) {
28-
if (forV2) {
29-
return (valueType instanceof BooleanType
30-
|| valueType instanceof IntegerType
31-
|| valueType instanceof StringType
32-
|| valueType instanceof DateType
33-
|| valueType instanceof LongType
34-
|| valueType instanceof TimestampType
35-
|| valueType instanceof FloatType
36-
|| valueType instanceof DoubleType);
37-
} else {
28+
default Boolean isSupportedType(DataType valueType, EvaluatorVersion version) {
29+
if (version == EvaluatorVersion.V2) {
3830
return (valueType instanceof BooleanType
39-
|| valueType instanceof IntegerType
40-
|| valueType instanceof StringType
41-
|| valueType instanceof DateType
42-
|| valueType instanceof LongType);
43-
}
31+
|| valueType instanceof IntegerType
32+
|| valueType instanceof StringType
33+
|| valueType instanceof DateType
34+
|| valueType instanceof LongType
35+
|| valueType instanceof TimestampType
36+
|| valueType instanceof FloatType
37+
|| valueType instanceof DoubleType);
38+
} else return (valueType instanceof BooleanType
39+
|| valueType instanceof IntegerType
40+
|| valueType instanceof StringType
41+
|| valueType instanceof DateType
42+
|| valueType instanceof LongType);
4443
}
4544

46-
Object eval(EvalContext ctx);
45+
Object eval(EvalContext ctx) throws PredicateException;
4746

48-
default Boolean evalExpectBoolean(EvalContext ctx) {
49-
return (Boolean) eval(ctx);
47+
default Boolean evalExpectBoolean(EvalContext ctx) throws PredicateException {
48+
var res = eval(ctx);
49+
if (res instanceof Boolean) {
50+
return (Boolean) res;
51+
} else {
52+
throw new WrongExpectedTypeException(res, Boolean.class);
53+
}
5054
}
5155

5256
List<BaseOp> getAllChildren();
@@ -60,44 +64,64 @@ default Boolean treeDepthExceeds(Integer depth) {
6064
}
6165
}
6266

67+
// marker interface for easier exception handling
68+
interface AryOp {};
69+
6370
// Represents a unary operation.
64-
interface UnaryOp {
71+
interface UnaryOp extends AryOp {
6572
// Validates number of children to be 1.
66-
default void validateChildren(List<BaseOp> children) {
73+
default void validateChildren(List<BaseOp> children) throws TypeNotSupportedException, PredicateValidationException, TypeMismatchException {
6774
if (children.size() != 1)
68-
throw new IllegalArgumentException(
69-
this + " : expected 1 but found " + children.size() + " children");
70-
children.get(0).validate();
75+
throw new PredicateValidationException(children.size(), this, 1);
76+
try {
77+
children.get(0).validate();
78+
} catch (PredicateException e) {
79+
throw new RuntimeException(e);
80+
}
7181
}
7282
}
7383

74-
interface BinaryOp {
84+
interface BinaryOp extends AryOp {
7585
// Validates number of children to be 2.
76-
default void validateChildren(List<BaseOp> children) {
86+
default void validateChildren(List<BaseOp> children) throws TypeMismatchException, PredicateValidationException, TypeNotSupportedException {
7787
if (children.size() != 2)
78-
throw new IllegalArgumentException(
79-
this + " : expected 2 but found " + children.size() + " children");
80-
children.forEach(BaseOp::validate);
88+
throw new PredicateValidationException(children.size(), this, 2);
89+
90+
// otherwise cannot throw exception in method call of lambda
91+
for (BaseOp c : children) {
92+
try {
93+
c.validate();
94+
} catch (PredicateException e) {
95+
throw new RuntimeException(e);
96+
}
97+
}
98+
8199
var child1 = children.get(0);
82100
var child2 = children.get(1);
83101
if (child1 instanceof LeafOp && child2 instanceof LeafOp) {
84102
var leftType = ((LeafOp) child1).getOpValueType();
85103
var rightType = ((LeafOp) child2).getOpValueType();
86104
if (!Objects.equals(leftType, rightType)) {
87-
throw new IllegalArgumentException("Type mismatch: " + leftType + " vs " + rightType
88-
+ " for " + child1 + " and " + child2);
105+
throw new TypeMismatchException(leftType, rightType);
89106
}
90107
}
91108
}
92109
}
93110

94-
interface NaryOp {
111+
// not used currently
112+
interface NaryOp extends AryOp {
95113
// Validates number of children to be at least 2.
96-
default void validateChildren(List<BaseOp> children) {
114+
default void validateChildren(List<BaseOp> children) throws PredicateValidationException, TypeNotSupportedException, TypeMismatchException {
97115
if (children.size() < 2) {
98-
throw new IllegalArgumentException(
99-
this + " : expected at least 2 but found " + children.size() + " children");
116+
throw new PredicateValidationException(children.size(), this, 2);
117+
}
118+
119+
for (BaseOp c : children) {
120+
try {
121+
c.validate();
122+
} catch (PredicateException e) {
123+
throw new RuntimeException(e);
124+
}
100125
}
101-
children.forEach(BaseOp::validate);
102126
}
103127
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.whitefox.core.types.predicates;
2+
3+
public enum BasePrimitiveTypeNames {
4+
DATE("date"),
5+
INT("int"),
6+
FLOAT("float"),
7+
DOUBLE("double"),
8+
TIMESTAMP("timestamp"),
9+
LONG("long"),
10+
STRING("string")
11+
;
12+
13+
final public String value;
14+
15+
BasePrimitiveTypeNames(String value) {
16+
this.value = value;
17+
}
18+
}
Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package io.whitefox.core.types.predicates;
22

3+
import com.fasterxml.jackson.core.JsonParseException;
34
import com.fasterxml.jackson.core.JsonParser;
45
import com.fasterxml.jackson.databind.DeserializationContext;
56
import com.fasterxml.jackson.databind.JsonNode;
67
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
78
import io.whitefox.core.types.*;
89
import java.io.IOException;
910

11+
12+
1013
public class DataTypeDeserializer extends StdDeserializer<DataType> {
1114

1215
// needed for jackson
@@ -22,25 +25,25 @@ public DataTypeDeserializer(Class<?> vc) {
2225
public DataType deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
2326
throws IOException {
2427
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
25-
String valueType = node.asText();
28+
String valueType = node.asText().toUpperCase();
2629

27-
switch (valueType) {
28-
case "date":
30+
switch (BasePrimitiveTypeNames.valueOf(valueType)) {
31+
case DATE:
2932
return DateType.DATE;
30-
case "int":
33+
case INT:
3134
return IntegerType.INTEGER;
32-
case "double":
35+
case DOUBLE:
3336
return DoubleType.DOUBLE;
34-
case "float":
37+
case FLOAT:
3538
return FloatType.FLOAT;
36-
case "string":
39+
case STRING:
3740
return StringType.STRING;
38-
case "timestamp":
41+
case TIMESTAMP:
3942
return TimestampType.TIMESTAMP;
40-
case "long":
43+
case LONG:
4144
return LongType.LONG;
4245
default:
43-
throw new IOException("Unknown type passed inside a json predicate: " + valueType);
46+
throw new JsonParseException("Unknown type passed inside a json predicate: " + valueType);
4447
}
4548
}
4649
}

0 commit comments

Comments
 (0)