99import org .elasticsearch .common .io .stream .StreamOutput ;
1010import org .elasticsearch .search .aggregations .InternalAggregation ;
1111import org .elasticsearch .search .aggregations .bucket .MultiBucketsAggregation .Bucket ;
12+ import org .elasticsearch .search .aggregations .matrix .stats .MatrixStats ;
1213import org .elasticsearch .search .aggregations .metrics .InternalNumericMetricsAggregation ;
14+ import org .elasticsearch .search .aggregations .metrics .InternalNumericMetricsAggregation .SingleValue ;
15+ import org .elasticsearch .search .aggregations .metrics .percentiles .PercentileRanks ;
16+ import org .elasticsearch .search .aggregations .metrics .percentiles .Percentiles ;
17+ import org .elasticsearch .search .aggregations .metrics .stats .InternalStats ;
1318import org .elasticsearch .xpack .sql .SqlIllegalArgumentException ;
1419import org .elasticsearch .xpack .sql .querydsl .agg .Aggs ;
1520
@@ -67,6 +72,11 @@ public Object extract(Bucket bucket) {
6772 if (agg == null ) {
6873 throw new SqlIllegalArgumentException ("Cannot find an aggregation named {}" , name );
6974 }
75+
76+ if (!containsValues (agg )) {
77+ return null ;
78+ }
79+
7080 if (agg instanceof InternalNumericMetricsAggregation .MultiValue ) {
7181 //TODO: need to investigate when this can be not-null
7282 //if (innerKey == null) {
@@ -79,6 +89,33 @@ public Object extract(Bucket bucket) {
7989 return innerKey != null && v instanceof Map ? ((Map <?, ?>) v ).get (innerKey ) : v ;
8090 }
8191
92+ /**
93+ * Check if the given aggregate has been executed and has computed values
94+ * or not (the bucket is null).
95+ *
96+ * Waiting on https://github.com/elastic/elasticsearch/issues/34903
97+ */
98+ private static boolean containsValues (InternalAggregation agg ) {
99+ // Stats & ExtendedStats
100+ if (agg instanceof InternalStats ) {
101+ return ((InternalStats ) agg ).getCount () != 0 ;
102+ }
103+ if (agg instanceof MatrixStats ) {
104+ return ((MatrixStats ) agg ).getDocCount () != 0 ;
105+ }
106+ // sum returns 0 even for null; since that's a common case, we return it as such
107+ if (agg instanceof SingleValue ) {
108+ return Double .isFinite (((SingleValue ) agg ).value ());
109+ }
110+ if (agg instanceof PercentileRanks ) {
111+ return Double .isFinite (((PercentileRanks ) agg ).percent (0 ));
112+ }
113+ if (agg instanceof Percentiles ) {
114+ return Double .isFinite (((Percentiles ) agg ).percentile (0 ));
115+ }
116+ return true ;
117+ }
118+
82119 @ Override
83120 public int hashCode () {
84121 return Objects .hash (name , property , innerKey );
0 commit comments