Skip to content

Commit 0195d1f

Browse files
vvysotskyiBen-Zvi
authored andcommitted
DRILL-7237: Fix single_value aggregate function for variable length types
- Add implementations of single_value for complex data types closes #1782
1 parent 0fa2967 commit 0195d1f

File tree

13 files changed

+442
-475
lines changed

13 files changed

+442
-475
lines changed

exec/java-exec/src/main/codegen/config.fmpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ data: {
4343
intervalNumericTypes: tdd(../data/IntervalNumericTypes.tdd),
4444
extract: tdd(../data/ExtractTypes.tdd),
4545
sumzero: tdd(../data/SumZero.tdd),
46-
singleValue: tdd(../data/SingleValue.tdd),
4746
numericTypes: tdd(../data/NumericTypes.tdd),
4847
casthigh: tdd(../data/CastHigh.tdd),
4948
countAggrTypes: tdd(../data/CountAggrTypes.tdd)

exec/java-exec/src/main/codegen/data/AggrTypes1.tdd

Lines changed: 98 additions & 50 deletions
Large diffs are not rendered by default.

exec/java-exec/src/main/codegen/data/DecimalAggrTypes1.tdd

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@
3939
{className: "AnyValue", funcName: "any_value", types: [
4040
{inputType: "VarDecimal", outputType: "NullableVarDecimal"},
4141
{inputType: "NullableVarDecimal", outputType: "NullableVarDecimal"}
42-
{inputType: "RepeatedVarDecimal", outputType: "RepeatedVarDecimal"}
42+
]
43+
},
44+
{className: "SingleValue", funcName: "single_value", types: [
45+
{inputType: "VarDecimal", outputType: "NullableVarDecimal"},
46+
{inputType: "NullableVarDecimal", outputType: "NullableVarDecimal"}
4347
]
4448
}
4549
]

exec/java-exec/src/main/codegen/data/SingleValue.tdd

Lines changed: 0 additions & 62 deletions
This file was deleted.

exec/java-exec/src/main/codegen/templates/AggrTypeFunctions1.java

Lines changed: 120 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -44,134 +44,137 @@
4444
@SuppressWarnings("unused")
4545

4646
public class ${aggrtype.className}Functions {
47-
static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(${aggrtype.className}Functions.class);
4847

4948
<#list aggrtype.types as type>
5049
<#if type.major == "Numeric">
5150

52-
@FunctionTemplate(name = "${aggrtype.funcName}", scope = FunctionTemplate.FunctionScope.POINT_AGGREGATE)
53-
public static class ${type.inputType}${aggrtype.className} implements DrillAggFunc{
54-
55-
@Param ${type.inputType}Holder in;
56-
@Workspace ${type.runningType}Holder value;
57-
@Workspace BigIntHolder nonNullCount;
58-
@Output ${type.outputType}Holder out;
59-
60-
public void setup() {
61-
value = new ${type.runningType}Holder();
62-
nonNullCount = new BigIntHolder();
63-
nonNullCount.value = 0;
64-
<#if aggrtype.funcName == "sum" || aggrtype.funcName == "any_value">
65-
value.value = 0;
66-
<#elseif aggrtype.funcName == "min">
67-
<#if type.runningType?starts_with("Bit")>
51+
@FunctionTemplate(name = "${aggrtype.funcName}",
52+
scope = FunctionTemplate.FunctionScope.POINT_AGGREGATE)
53+
public static class ${type.inputType}${aggrtype.className} implements DrillAggFunc {
54+
@Param ${type.inputType}Holder in;
55+
@Workspace ${type.runningType}Holder value;
56+
@Workspace BigIntHolder nonNullCount;
57+
@Output ${type.outputType}Holder out;
58+
59+
public void setup() {
60+
value = new ${type.runningType}Holder();
61+
nonNullCount = new BigIntHolder();
62+
nonNullCount.value = 0;
63+
<#if aggrtype.funcName == "sum" || aggrtype.funcName == "any_value" || aggrtype.funcName == "single_value">
64+
value.value = 0;
65+
<#elseif aggrtype.funcName == "min">
66+
<#if type.runningType?starts_with("Bit")>
6867
value.value = 1;
69-
<#elseif type.runningType?starts_with("Int")>
70-
value.value = Integer.MAX_VALUE;
71-
<#elseif type.runningType?starts_with("BigInt")>
72-
value.value = Long.MAX_VALUE;
73-
<#elseif type.runningType?starts_with("Float4")>
74-
value.value = Float.NaN;
75-
<#elseif type.runningType?starts_with("Float8")>
76-
value.value = Double.NaN;
77-
</#if>
78-
<#elseif aggrtype.funcName == "max">
79-
<#if type.runningType?starts_with("Bit")>
68+
<#elseif type.runningType?starts_with("Int")>
69+
value.value = Integer.MAX_VALUE;
70+
<#elseif type.runningType?starts_with("BigInt")>
71+
value.value = Long.MAX_VALUE;
72+
<#elseif type.runningType?starts_with("Float4")>
73+
value.value = Float.NaN;
74+
<#elseif type.runningType?starts_with("Float8")>
75+
value.value = Double.NaN;
76+
</#if>
77+
<#elseif aggrtype.funcName == "max">
78+
<#if type.runningType?starts_with("Bit")>
8079
value.value = 0;
81-
<#elseif type.runningType?starts_with("Int")>
82-
value.value = Integer.MIN_VALUE;
83-
<#elseif type.runningType?starts_with("BigInt")>
84-
value.value = Long.MIN_VALUE;
85-
<#elseif type.runningType?starts_with("Float4")>
86-
value.value = -Float.MAX_VALUE;
87-
<#elseif type.runningType?starts_with("Float8")>
88-
value.value = -Double.MAX_VALUE;
89-
</#if>
90-
</#if>
91-
92-
}
93-
94-
@Override
95-
public void add() {
96-
<#if type.inputType?starts_with("Nullable")>
97-
sout: {
98-
if (in.isSet == 0) {
99-
// processing nullable input and the value is null, so don't do anything...
100-
break sout;
101-
}
102-
</#if>
103-
nonNullCount.value = 1;
104-
// For min/max functions: NaN is the biggest value,
105-
// Infinity is the second biggest value
106-
// -Infinity is the smallest value
107-
<#if aggrtype.funcName == "min">
108-
<#if type.inputType?contains("Float4")>
109-
if(!Float.isNaN(in.value)) {
110-
value.value = Float.isNaN(value.value) ? in.value : Math.min(value.value, in.value);
111-
}
112-
<#elseif type.inputType?contains("Float8")>
113-
if(!Double.isNaN(in.value)) {
114-
value.value = Double.isNaN(value.value) ? in.value : Math.min(value.value, in.value);
115-
}
80+
<#elseif type.runningType?starts_with("Int")>
81+
value.value = Integer.MIN_VALUE;
82+
<#elseif type.runningType?starts_with("BigInt")>
83+
value.value = Long.MIN_VALUE;
84+
<#elseif type.runningType?starts_with("Float4")>
85+
value.value = -Float.MAX_VALUE;
86+
<#elseif type.runningType?starts_with("Float8")>
87+
value.value = -Double.MAX_VALUE;
88+
</#if>
89+
</#if>
90+
}
91+
92+
@Override
93+
public void add() {
94+
<#if type.inputType?starts_with("Nullable")>
95+
sout: {
96+
if (in.isSet == 0) {
97+
// processing nullable input and the value is null, so don't do anything...
98+
break sout;
99+
}
100+
</#if>
101+
<#if aggrtype.funcName == "single_value">
102+
if (nonNullCount.value > 0) {
103+
throw org.apache.drill.common.exceptions.UserException.functionError()
104+
.message("Input for single_value function has more than one row")
105+
.build();
106+
}
107+
</#if>
108+
nonNullCount.value = 1;
109+
// For min/max functions: NaN is the biggest value,
110+
// Infinity is the second biggest value
111+
// -Infinity is the smallest value
112+
<#if aggrtype.funcName == "min">
113+
<#if type.inputType?contains("Float4")>
114+
if(!Float.isNaN(in.value)) {
115+
value.value = Float.isNaN(value.value) ? in.value : Math.min(value.value, in.value);
116+
}
117+
<#elseif type.inputType?contains("Float8")>
118+
if(!Double.isNaN(in.value)) {
119+
value.value = Double.isNaN(value.value) ? in.value : Math.min(value.value, in.value);
120+
}
121+
<#else>
122+
value.value = Math.min(value.value, in.value);
123+
</#if>
124+
<#elseif aggrtype.funcName == "max">
125+
value.value = Math.max(value.value, in.value);
126+
<#elseif aggrtype.funcName == "sum">
127+
value.value += in.value;
128+
<#elseif aggrtype.funcName == "count">
129+
value.value++;
130+
<#elseif aggrtype.funcName == "any_value" || aggrtype.funcName == "single_value">
131+
value.value = in.value;
116132
<#else>
117-
value.value = Math.min(value.value, in.value);
118-
</#if>
119-
<#elseif aggrtype.funcName == "max">
120-
value.value = Math.max(value.value, in.value);
121-
<#elseif aggrtype.funcName == "sum">
122-
value.value += in.value;
123-
<#elseif aggrtype.funcName == "count">
124-
value.value++;
125-
<#elseif aggrtype.funcName == "any_value">
126-
value.value = in.value;
127-
<#else>
128-
// TODO: throw an error ?
129-
</#if>
130-
<#if type.inputType?starts_with("Nullable")>
131-
} // end of sout block
132-
</#if>
133-
}
133+
// TODO: throw an error ?
134+
</#if>
135+
<#if type.inputType?starts_with("Nullable")>
136+
} // end of sout block
137+
</#if>
138+
}
134139

135-
@Override
136-
public void output() {
137-
if (nonNullCount.value > 0) {
138-
out.value = value.value;
139-
out.isSet = 1;
140-
} else {
141-
out.isSet = 0;
140+
@Override
141+
public void output() {
142+
if (nonNullCount.value > 0) {
143+
out.value = value.value;
144+
out.isSet = 1;
145+
} else {
146+
out.isSet = 0;
147+
}
142148
}
143-
}
144149

145-
@Override
146-
public void reset() {
147-
nonNullCount.value = 0;
148-
<#if aggrtype.funcName == "sum" || aggrtype.funcName == "count" || aggrtype.funcName == "any_value">
149-
value.value = 0;
150-
<#elseif aggrtype.funcName == "min">
151-
<#if type.runningType?starts_with("Int")>
152-
value.value = Integer.MAX_VALUE;
153-
<#elseif type.runningType?starts_with("BigInt")>
154-
value.value = Long.MAX_VALUE;
155-
<#elseif type.runningType?starts_with("Float4")>
156-
value.value = Float.NaN;
157-
<#elseif type.runningType?starts_with("Float8")>
158-
value.value = Double.NaN;
159-
</#if>
160-
<#elseif aggrtype.funcName == "max">
161-
<#if type.runningType?starts_with("Int")>
162-
value.value = Integer.MIN_VALUE;
163-
<#elseif type.runningType?starts_with("BigInt")>
164-
value.value = Long.MIN_VALUE;
165-
<#elseif type.runningType?starts_with("Float4")>
166-
value.value = -Float.MAX_VALUE;
167-
<#elseif type.runningType?starts_with("Float8")>
168-
value.value = -Double.MAX_VALUE;
169-
</#if>
170-
</#if>
171-
150+
@Override
151+
public void reset() {
152+
nonNullCount.value = 0;
153+
<#if aggrtype.funcName == "sum" || aggrtype.funcName == "count" || aggrtype.funcName == "any_value" || aggrtype.funcName == "single_value">
154+
value.value = 0;
155+
<#elseif aggrtype.funcName == "min">
156+
<#if type.runningType?starts_with("Int")>
157+
value.value = Integer.MAX_VALUE;
158+
<#elseif type.runningType?starts_with("BigInt")>
159+
value.value = Long.MAX_VALUE;
160+
<#elseif type.runningType?starts_with("Float4")>
161+
value.value = Float.NaN;
162+
<#elseif type.runningType?starts_with("Float8")>
163+
value.value = Double.NaN;
164+
</#if>
165+
<#elseif aggrtype.funcName == "max">
166+
<#if type.runningType?starts_with("Int")>
167+
value.value = Integer.MIN_VALUE;
168+
<#elseif type.runningType?starts_with("BigInt")>
169+
value.value = Long.MIN_VALUE;
170+
<#elseif type.runningType?starts_with("Float4")>
171+
value.value = -Float.MAX_VALUE;
172+
<#elseif type.runningType?starts_with("Float8")>
173+
value.value = -Double.MAX_VALUE;
174+
</#if>
175+
</#if>
176+
}
172177
}
173-
174-
}
175178

176179
</#if>
177180
</#list>

0 commit comments

Comments
 (0)