1616import org .elasticsearch .compute .data .BytesRefBlock ;
1717import org .elasticsearch .compute .data .BytesRefVector ;
1818import org .elasticsearch .compute .data .IntBlock ;
19+ import org .elasticsearch .compute .data .IntVector ;
1920import org .elasticsearch .compute .data .OrdinalBytesRefBlock ;
2021import org .elasticsearch .core .Releasable ;
2122import org .elasticsearch .core .Releasables ;
@@ -77,11 +78,6 @@ public long estimatedBytes() {
7778
7879 @ Override
7980 public BytesRefBlock build () {
80- // TODO: detect when constant block can be used like is done in: https://github.com/elastic/elasticsearch/pull/132456
81- return buildOrdinal ();
82- }
83-
84- BytesRefBlock buildOrdinal () {
8581 assert ords .length == count ;
8682
8783 int minOrd ;
@@ -106,8 +102,16 @@ BytesRefBlock buildOrdinal() {
106102 minOrd = Math .toIntExact (tmpMinOrd );
107103 maxOrd = Math .toIntExact (tmpMaxOrd );
108104 }
105+
106+ var constantBlock = tryBuildConstantBlock (minOrd , maxOrd );
107+ if (constantBlock != null ) {
108+ return constantBlock ;
109+ }
109110 int valueCount = maxOrd - minOrd + 1 ;
111+ return buildOrdinal (minOrd , maxOrd , valueCount , isDense );
112+ }
110113
114+ BytesRefBlock buildOrdinal (int minOrd , int maxOrd , int valueCount , boolean isDense ) {
111115 long breakerSize = ordsSize (count );
112116 blockFactory .adjustBreaker (breakerSize );
113117
@@ -147,6 +151,35 @@ BytesRefBlock buildOrdinal() {
147151 }
148152 }
149153
154+ private BytesRefBlock tryBuildConstantBlock (int minOrd , int maxOrd ) {
155+ if (minOrd != maxOrd ) {
156+ return null ;
157+ }
158+
159+ final BytesRef v ;
160+ try {
161+ v = BytesRef .deepCopyOf (docValues .lookupOrd (minOrd ));
162+ } catch (IOException e ) {
163+ throw new UncheckedIOException (e );
164+ }
165+ BytesRefVector bytes = null ;
166+ IntVector ordinals = null ;
167+ boolean success = false ;
168+ try {
169+ bytes = blockFactory .newConstantBytesRefVector (v , 1 );
170+ ordinals = blockFactory .newConstantIntVector (0 , ords .length );
171+ // Ideally, we would return a ConstantBytesRefVector, but we return an ordinal constant block instead
172+ // to ensure ordinal optimizations are applied when constant optimization is not available.
173+ final var result = new OrdinalBytesRefBlock (ordinals .asBlock (), bytes );
174+ success = true ;
175+ return result ;
176+ } finally {
177+ if (success == false ) {
178+ Releasables .close (bytes , ordinals );
179+ }
180+ }
181+ }
182+
150183 @ Override
151184 public void close () {
152185 blockFactory .adjustBreaker (-nativeOrdsSize (ords .length ));
0 commit comments