Skip to content
Merged
402 changes: 201 additions & 201 deletions x-pack/plugin/esql/qa/testFixtures/src/main/resources/data/k8s.csv

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
}
}
},
"region": {
"type": "keyword",
"time_series_dimension": true
},
"event": {
"type": "keyword"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ events:double | pod:keyword | time_bucket:datetime
15.746543778801843 | one | 2024-05-10T00:00:00.000Z
15.396284829721363 | three | 2024-05-10T00:00:00.000Z
15.045454545454547 | three | 2024-05-10T00:10:00.000Z
14.199942045783832 | two | 2024-05-10T00:00:00.000Z
14.19994204578383 | two | 2024-05-10T00:00:00.000Z
11.5 | two | 2024-05-10T00:20:00.000Z
;

Expand Down Expand Up @@ -235,13 +235,13 @@ sum:double | pod:keyword | time_bucket:datetime

avg_over_time_nested_expression_in_grouping_with_alias
required_capability: ts_command_v0
TS k8s | STATS min = min(avg_over_time(network.bytes_in)) by time_bucket = bucket(date_trunc(2 minutes, @timestamp), 5 minutes) | SORT time_bucket | LIMIT 5;
TS k8s | STATS min = min(avg_over_time(network.bytes_in)) by time_bucket = bucket(@timestamp, 5 minutes) | SORT time_bucket | LIMIT 5;

min:double | time_bucket:datetime
382.0416666666667 | 2024-05-10T00:00:00.000Z
382.0416666666667 | 2024-05-10T00:05:00.000Z
382.0416666666667 | 2024-05-10T00:10:00.000Z
382.0416666666667 | 2024-05-10T00:15:00.000Z
382.0416666666667 | 2024-05-10T00:20:00.000Z
307.6666666666667 | 2024-05-10T00:00:00.000Z
194.5 | 2024-05-10T00:05:00.000Z
46.75 | 2024-05-10T00:10:00.000Z
260.0 | 2024-05-10T00:15:00.000Z
174.2 | 2024-05-10T00:20:00.000Z

;
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ TS k8s

irate_cost:double | time_bucket:datetime
null | 2024-05-10T00:01:00.000Z
7.836832264957264 | 2024-05-10T00:09:00.000Z
7.836832264957265 | 2024-05-10T00:09:00.000Z
3.590324074074074 | 2024-05-10T00:17:00.000Z
2.6708333333333334 | 2024-05-10T00:02:00.000Z
2.2916666666666665 | 2024-05-10T00:08:00.000Z
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,22 @@ TS k8s

;

sum_rate_per_region
required_capability: ts_command_v0
required_capability: pack_dimensions_in_ts
TS k8s
| STATS rate_bytes_in=avg(rate(network.total_bytes_in)) BY cluster, region, time_bucket = bucket(@timestamp,5minute)
| SORT rate_bytes_in DESC, time_bucket, cluster | LIMIT 10;

rate_bytes_in:double | cluster:keyword | region:keyword | time_bucket:datetime
15.025267167998313 | qa | null | 2024-05-10T00:15:00.000Z
13.638384356589611 | qa | null | 2024-05-10T00:05:00.000Z
11.761724575728252 | prod | [eu, us] | 2024-05-10T00:15:00.000Z
7.453275209904956 | qa | null | 2024-05-10T00:10:00.000Z
7.307225056633641 | staging | us | 2024-05-10T00:05:00.000Z
7.203958127639015 | prod | [eu, us] | 2024-05-10T00:10:00.000Z
6.34494062999877 | staging | us | 2024-05-10T00:10:00.000Z
5.700488689624205 | prod | [eu, us] | 2024-05-10T00:20:00.000Z
5.4539153439153445 | prod | [eu, us] | 2024-05-10T00:00:00.000Z
Copy link
Member Author

Choose a reason for hiding this comment

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

We return arrays for grouping dimensions.

5.241187469367376 | staging | us | 2024-05-10T00:00:00.000Z
;
Original file line number Diff line number Diff line change
Expand Up @@ -220,13 +220,13 @@ sum:long | pod:keyword | time_bucket:datetime

sum_over_time_nested_expression_in_grouping_with_alias
required_capability: ts_command_v0
TS k8s | STATS min = min(sum_over_time(network.bytes_in)) by time_bucket = bucket(date_trunc(2 minutes, @timestamp), 5 minutes) | SORT time_bucket | LIMIT 10;
TS k8s | STATS min = min(sum_over_time(network.bytes_in)) by time_bucket = bucket(@timestamp, 5 minutes) | SORT time_bucket | LIMIT 10;


min:long | time_bucket:datetime
6160 | 2024-05-10T00:00:00.000Z
6160 | 2024-05-10T00:05:00.000Z
6160 | 2024-05-10T00:10:00.000Z
6160 | 2024-05-10T00:15:00.000Z
6160 | 2024-05-10T00:20:00.000Z
651 | 2024-05-10T00:00:00.000Z
389 | 2024-05-10T00:05:00.000Z
187 | 2024-05-10T00:10:00.000Z
520 | 2024-05-10T00:15:00.000Z
774 | 2024-05-10T00:20:00.000Z
;
Original file line number Diff line number Diff line change
Expand Up @@ -4742,7 +4742,7 @@ FROM k8s
| RENAME network.bytes_in AS language_code
| WHERE language_code < 10
| LOOKUP JOIN languages_lookup ON language_code
| DROP network*, event*
| DROP network*, event*, region
| SORT language_code, @timestamp
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1504,7 +1504,14 @@ public enum Cap {
/**
* Support for the literal {@code m} suffix as an alias for {@code minute} in temporal amounts.
*/
TEMPORAL_AMOUNT_M;
TEMPORAL_AMOUNT_M,

/**
* Pack dimension values in TS command
*/
PACK_DIMENSIONS_IN_TS

;

private final boolean enabled;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.esql.expression.function.scalar.internal;

import org.apache.lucene.util.BytesRef;
import org.elasticsearch.compute.data.BooleanBlock;
import org.elasticsearch.compute.data.BytesRefBlock;
import org.elasticsearch.compute.data.BytesRefVector;
import org.elasticsearch.compute.data.IntBlock;
import org.elasticsearch.compute.data.LongBlock;
import org.elasticsearch.compute.data.OrdinalBytesRefVector;
import org.elasticsearch.compute.operator.BreakingBytesRefBuilder;
import org.elasticsearch.compute.operator.DriverContext;
import org.elasticsearch.compute.operator.topn.TopNEncoder;

final class InternalPacks {
private static final TopNEncoder ENCODER = TopNEncoder.DEFAULT_UNSORTABLE;
public static final int INITIAL_SIZE_IN_BYTES = 6 * 1024;

static int estimateForBytesBuilder(int positionCount) {
// allocate at least one page for the bytes block builder to avoid copying during resizing
return Math.max(INITIAL_SIZE_IN_BYTES, positionCount);
}

static BytesRefBlock packBytesValues(DriverContext driverContext, BytesRefBlock raw) {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is where we encode multi-valued block into a single value.

BytesRefVector vector = raw.asVector();
if (vector != null) {
OrdinalBytesRefVector ordinals = vector.asOrdinals();
if (ordinals != null) {
var encoded = packBytesVector(driverContext, ordinals.getDictionaryVector());
ordinals.getOrdinalsVector().incRef();
return new OrdinalBytesRefVector(ordinals.getOrdinalsVector(), encoded).asBlock();
} else {
return packBytesVector(driverContext, vector).asBlock();
}
}
int positionCount = raw.getPositionCount();
try (
var builder = driverContext.blockFactory().newBytesRefBlockBuilder(estimateForBytesBuilder(positionCount));
var work = new BreakingBytesRefBuilder(driverContext.breaker(), "pack_dimensions", 1024)
) {
BytesRef scratch = new BytesRef();
for (int p = 0; p < positionCount; p++) {
int valueCount = raw.getValueCount(p);
if (valueCount == 0) {
builder.appendNull();
continue;
}
work.clear();
int first = raw.getFirstValueIndex(p);
int end = first + valueCount;
for (int i = first; i < end; i++) {
raw.getBytesRef(i, scratch);
ENCODER.encodeBytesRef(scratch, work);
}
builder.appendBytesRef(work.bytesRefView());
}
return builder.build();
}
}

static BytesRefVector packBytesVector(DriverContext driverContext, BytesRefVector encode) {
int positionCount = encode.getPositionCount();
try (
var builder = driverContext.blockFactory().newBytesRefVectorBuilder(estimateForBytesBuilder(positionCount));
var work = new BreakingBytesRefBuilder(driverContext.breaker(), "pack_values", 1024)
) {
BytesRef scratch = new BytesRef();
for (int p = 0; p < positionCount; p++) {
ENCODER.encodeBytesRef(encode.getBytesRef(p, scratch), work);
builder.appendBytesRef(work.bytesRefView());
work.clear();
}
return builder.build();
}
}

static BytesRefBlock unpackBytesValues(DriverContext driverContext, BytesRefBlock encoded) {
Copy link
Member Author

Choose a reason for hiding this comment

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

And decode here.

int positionCount = encoded.getPositionCount();
try (var builder = driverContext.blockFactory().newBytesRefBlockBuilder(estimateForBytesBuilder(positionCount));) {
BytesRef inScratch = new BytesRef();
BytesRef outScratch = new BytesRef();
for (int p = 0; p < positionCount; p++) {
if (encoded.isNull(p)) {
builder.appendNull();
continue;
}
BytesRef row = encoded.getBytesRef(p, inScratch);
var v = ENCODER.decodeBytesRef(row, outScratch);
if (row.length == 0) {
builder.appendBytesRef(v);
} else {
builder.beginPositionEntry();
builder.appendBytesRef(v);
while (row.length > 0) {
v = ENCODER.decodeBytesRef(row, outScratch);
builder.appendBytesRef(v);
}
builder.endPositionEntry();
}
}
return builder.build();
}
}

static BytesRefBlock packLongValues(DriverContext driverContext, LongBlock raw) {
int positionCount = raw.getPositionCount();
try (
var builder = driverContext.blockFactory().newBytesRefBlockBuilder(estimateForBytesBuilder(positionCount));
var work = new BreakingBytesRefBuilder(driverContext.breaker(), "pack_values", 32)
) {
for (int p = 0; p < positionCount; p++) {
int valueCount = raw.getValueCount(p);
if (valueCount == 0) {
builder.appendNull();
continue;
}
work.clear();
int first = raw.getFirstValueIndex(p);
if (valueCount == 1) {
ENCODER.encodeLong(raw.getLong(first), work);
} else {
int end = first + valueCount;
for (int i = first; i < end; i++) {
ENCODER.encodeLong(raw.getLong(i), work);
}
}
builder.appendBytesRef(work.bytesRefView());
}
return builder.build();
}
}

static LongBlock unpackLongValues(DriverContext driverContext, BytesRefBlock encoded) {
int positionCount = encoded.getPositionCount();
try (var builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) {
BytesRef inScratch = new BytesRef();
for (int p = 0; p < positionCount; p++) {
if (encoded.isNull(p)) {
builder.appendNull();
continue;
}
BytesRef row = encoded.getBytesRef(p, inScratch);
var v = ENCODER.decodeLong(row);
if (row.length == 0) {
builder.appendLong(v);
} else {
builder.beginPositionEntry();
builder.appendLong(v);
while (row.length > 0) {
builder.appendLong(ENCODER.decodeLong(row));
}
builder.endPositionEntry();
}
}
return builder.build();
}
}

static BytesRefBlock packIntValues(DriverContext driverContext, IntBlock raw) {
int positionCount = raw.getPositionCount();
try (
var builder = driverContext.blockFactory().newBytesRefBlockBuilder(estimateForBytesBuilder(positionCount));
var work = new BreakingBytesRefBuilder(driverContext.breaker(), "pack_values", 32)
) {
for (int p = 0; p < positionCount; p++) {
int valueCount = raw.getValueCount(p);
if (valueCount == 0) {
builder.appendNull();
continue;
}
work.clear();
int first = raw.getFirstValueIndex(p);
if (valueCount == 1) {
ENCODER.encodeInt(raw.getInt(first), work);
} else {
int end = first + valueCount;
for (int i = first; i < end; i++) {
ENCODER.encodeInt(raw.getInt(i), work);
}
}
builder.appendBytesRef(work.bytesRefView());
}
return builder.build();
}
}

static IntBlock unpackIntValues(DriverContext driverContext, BytesRefBlock encoded) {
int positionCount = encoded.getPositionCount();
try (IntBlock.Builder builder = driverContext.blockFactory().newIntBlockBuilder(positionCount)) {
BytesRef inScratch = new BytesRef();
for (int p = 0; p < positionCount; p++) {
if (encoded.isNull(p)) {
builder.appendNull();
continue;
}
BytesRef row = encoded.getBytesRef(p, inScratch);
int v = ENCODER.decodeInt(row);
if (row.length == 0) {
builder.appendInt(v);
} else {
builder.beginPositionEntry();
builder.appendInt(v);
while (row.length > 0) {
builder.appendInt(ENCODER.decodeInt(row));
}
builder.endPositionEntry();
}
}
return builder.build();
}
}

static BytesRefBlock packBooleanValues(DriverContext driverContext, BooleanBlock raw) {
int positionCount = raw.getPositionCount();
try (
var builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount);
var work = new BreakingBytesRefBuilder(driverContext.breaker(), "pack_values", 32)
) {
for (int p = 0; p < positionCount; p++) {
work.clear();
int valueCount = raw.getValueCount(p);
if (valueCount == 0) {
builder.appendNull();
continue;
}
int first = raw.getFirstValueIndex(p);
if (valueCount == 1) {
ENCODER.encodeBoolean(raw.getBoolean(first), work);
} else {
int end = first + valueCount;
for (int i = first; i < end; i++) {
ENCODER.encodeBoolean(raw.getBoolean(i), work);
}
}
builder.appendBytesRef(work.bytesRefView());
}
return builder.build();
}
}

static BooleanBlock unpackBooleanValues(DriverContext driverContext, BytesRefBlock encoded) {
int positionCount = encoded.getPositionCount();
try (var builder = driverContext.blockFactory().newBooleanBlockBuilder(positionCount)) {
BytesRef inScratch = new BytesRef();
for (int p = 0; p < positionCount; p++) {
if (encoded.isNull(p)) {
builder.appendNull();
continue;
}
BytesRef row = encoded.getBytesRef(p, inScratch);
boolean v = ENCODER.decodeBoolean(row);
if (row.length == 0) {
builder.appendBoolean(v);
} else {
builder.beginPositionEntry();
builder.appendBoolean(v);
while (row.length > 0) {
builder.appendBoolean(ENCODER.decodeBoolean(row));
}
builder.endPositionEntry();
}
}
return builder.build();
}
}
}
Loading