diff --git a/pkg/dataobj/sections/logs/table.go b/pkg/dataobj/sections/logs/table.go index 80794af519ffb..d4fefd4a8dda8 100644 --- a/pkg/dataobj/sections/logs/table.go +++ b/pkg/dataobj/sections/logs/table.go @@ -340,7 +340,7 @@ func (b *tableBuffer) Flush() (*table, error) { // Each metadata column may have a different number of rows compared to // other columns. Backfill them with NULLs to match the max rows in the buffer. - // It is safe to use streamID column row count since it is a requried column in logs section. + // It is safe to use streamID column row count since it is a required column in logs section. metadataBuilder.Backfill(streamID.Desc.RowsCount) metadata, _ := metadataBuilder.Flush() diff --git a/pkg/engine/compat_bench_test.go b/pkg/engine/compat_bench_test.go index f8b8fcd34ca7e..5329d4994d5c8 100644 --- a/pkg/engine/compat_bench_test.go +++ b/pkg/engine/compat_bench_test.go @@ -8,6 +8,7 @@ import ( "github.com/apache/arrow-go/v18/arrow" "github.com/apache/arrow-go/v18/arrow/memory" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/util/arrowtest" @@ -97,7 +98,7 @@ func prepareSchema(numLabels int, numMeta int, numParsed int) (*arrow.Schema, [] for i := 0; i < numLabels; i++ { ident := semconv.NewIdentifier( fmt.Sprintf("label_%d", i), - types.ColumnTypeLabel, + physicalpb.COLUMN_TYPE_LABEL, types.Loki.String, ) labelIdents[i] = ident @@ -109,7 +110,7 @@ func prepareSchema(numLabels int, numMeta int, numParsed int) (*arrow.Schema, [] for i := 0; i < numMeta; i++ { ident := semconv.NewIdentifier( fmt.Sprintf("meta_%d", i), - types.ColumnTypeMetadata, + physicalpb.COLUMN_TYPE_METADATA, types.Loki.String, ) metaIdents[i] = ident @@ -121,7 +122,7 @@ func prepareSchema(numLabels int, numMeta int, numParsed int) (*arrow.Schema, [] for i := 0; i < numParsed; i++ { ident := semconv.NewIdentifier( fmt.Sprintf("parsed_%d", i), - types.ColumnTypeParsed, + physicalpb.COLUMN_TYPE_PARSED, types.Loki.String, ) parsedIdents[i] = ident diff --git a/pkg/engine/compat_test.go b/pkg/engine/compat_test.go index ca526cc7ee610..008efb7c9ce3a 100644 --- a/pkg/engine/compat_test.go +++ b/pkg/engine/compat_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/loki/v3/pkg/engine/internal/executor" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/logproto" @@ -33,7 +34,7 @@ func TestStreamsResultBuilder(t *testing.T) { t.Run("rows without log line, timestamp, or labels are ignored", func(t *testing.T) { colTs := semconv.ColumnIdentTimestamp colMsg := semconv.ColumnIdentMessage - colEnv := semconv.NewIdentifier("env", types.ColumnTypeMetadata, types.Loki.String) + colEnv := semconv.NewIdentifier("env", physicalpb.COLUMN_TYPE_METADATA, types.Loki.String) schema := arrow.NewSchema( []arrow.Field{ @@ -76,9 +77,9 @@ func TestStreamsResultBuilder(t *testing.T) { t.Run("successful conversion of labels, log line, timestamp, and structured metadata ", func(t *testing.T) { colTs := semconv.ColumnIdentTimestamp colMsg := semconv.ColumnIdentMessage - colEnv := semconv.NewIdentifier("env", types.ColumnTypeLabel, types.Loki.String) - colNs := semconv.NewIdentifier("namespace", types.ColumnTypeLabel, types.Loki.String) - colTid := semconv.NewIdentifier("traceID", types.ColumnTypeMetadata, types.Loki.String) + colEnv := semconv.NewIdentifier("env", physicalpb.COLUMN_TYPE_LABEL, types.Loki.String) + colNs := semconv.NewIdentifier("namespace", physicalpb.COLUMN_TYPE_LABEL, types.Loki.String) + colTid := semconv.NewIdentifier("traceID", physicalpb.COLUMN_TYPE_METADATA, types.Loki.String) schema := arrow.NewSchema( []arrow.Field{ @@ -201,7 +202,7 @@ func TestStreamsResultBuilder(t *testing.T) { t.Run("multiple records with different streams are accumulated correctly", func(t *testing.T) { colTs := semconv.ColumnIdentTimestamp colMsg := semconv.ColumnIdentMessage - colEnv := semconv.NewIdentifier("env", types.ColumnTypeLabel, types.Loki.String) + colEnv := semconv.NewIdentifier("env", physicalpb.COLUMN_TYPE_LABEL, types.Loki.String) schema := arrow.NewSchema( []arrow.Field{ @@ -289,7 +290,7 @@ func TestStreamsResultBuilder(t *testing.T) { t.Run("buffer reuse with varying record sizes", func(t *testing.T) { colTs := semconv.ColumnIdentTimestamp colMsg := semconv.ColumnIdentMessage - colEnv := semconv.NewIdentifier("env", types.ColumnTypeLabel, types.Loki.String) + colEnv := semconv.NewIdentifier("env", physicalpb.COLUMN_TYPE_LABEL, types.Loki.String) schema := arrow.NewSchema( []arrow.Field{ @@ -358,7 +359,7 @@ func TestStreamsResultBuilder(t *testing.T) { t.Run("empty records mixed with valid records", func(t *testing.T) { colTs := semconv.ColumnIdentTimestamp colMsg := semconv.ColumnIdentMessage - colEnv := semconv.NewIdentifier("env", types.ColumnTypeLabel, types.Loki.String) + colEnv := semconv.NewIdentifier("env", physicalpb.COLUMN_TYPE_LABEL, types.Loki.String) schema := arrow.NewSchema( []arrow.Field{ @@ -432,8 +433,8 @@ func TestVectorResultBuilder(t *testing.T) { t.Run("successful conversion of vector data", func(t *testing.T) { colTs := semconv.ColumnIdentTimestamp colVal := semconv.ColumnIdentValue - colInst := semconv.NewIdentifier("instance", types.ColumnTypeMetadata, types.Loki.String) - colJob := semconv.NewIdentifier("job", types.ColumnTypeMetadata, types.Loki.String) + colInst := semconv.NewIdentifier("instance", physicalpb.COLUMN_TYPE_METADATA, types.Loki.String) + colJob := semconv.NewIdentifier("job", physicalpb.COLUMN_TYPE_METADATA, types.Loki.String) schema := arrow.NewSchema( []arrow.Field{ @@ -496,7 +497,7 @@ func TestVectorResultBuilder(t *testing.T) { t.Run("rows without timestamp or value are ignored", func(t *testing.T) { colTs := semconv.ColumnIdentTimestamp colVal := semconv.ColumnIdentValue - colInst := semconv.NewIdentifier("instance", types.ColumnTypeMetadata, types.Loki.String) + colInst := semconv.NewIdentifier("instance", physicalpb.COLUMN_TYPE_METADATA, types.Loki.String) schema := arrow.NewSchema( []arrow.Field{ @@ -534,8 +535,8 @@ func TestMatrixResultBuilder(t *testing.T) { t.Run("successful conversion of matrix data", func(t *testing.T) { colTs := semconv.ColumnIdentTimestamp colVal := semconv.ColumnIdentValue - colInst := semconv.NewIdentifier("instance", types.ColumnTypeMetadata, types.Loki.String) - colJob := semconv.NewIdentifier("job", types.ColumnTypeMetadata, types.Loki.String) + colInst := semconv.NewIdentifier("instance", physicalpb.COLUMN_TYPE_METADATA, types.Loki.String) + colJob := semconv.NewIdentifier("job", physicalpb.COLUMN_TYPE_METADATA, types.Loki.String) schema := arrow.NewSchema( []arrow.Field{ diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 47b75459cfb89..496da51bf314b 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -23,6 +23,7 @@ import ( "github.com/grafana/loki/v3/pkg/engine/internal/executor" "github.com/grafana/loki/v3/pkg/engine/internal/planner/logical" "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/logql" "github.com/grafana/loki/v3/pkg/logql/syntax" "github.com/grafana/loki/v3/pkg/logqlmodel" @@ -181,7 +182,7 @@ func (e *QueryEngine) Execute(ctx context.Context, params logql.Params) (logqlmo return logqlmodel.Result{}, err } - physicalPlan, err := func() (*physical.Plan, error) { + physicalPlan, err := func() (*physicalpb.Plan, error) { ctx, span := tracer.Start(ctx, "QueryEngine.Execute.physicalPlan") defer span.End() diff --git a/pkg/engine/internal/executor/aggregator.go b/pkg/engine/internal/executor/aggregator.go index 6af7555e0b8e3..c177f2bd15ad2 100644 --- a/pkg/engine/internal/executor/aggregator.go +++ b/pkg/engine/internal/executor/aggregator.go @@ -1,7 +1,6 @@ package executor import ( - "fmt" "maps" "slices" "strings" @@ -12,7 +11,7 @@ import ( "github.com/apache/arrow-go/v18/arrow/memory" "github.com/cespare/xxhash/v2" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) @@ -33,7 +32,7 @@ const ( // aggregator is used to aggregate sample values by a set of grouping keys for each point in time. type aggregator struct { - groupBy []physical.ColumnExpression // columns to group by + groupBy []*physicalpb.ColumnExpression // columns to group by points map[time.Time]map[uint64]*groupState // holds the groupState for each point in time series digest *xxhash.Digest // used to compute key for each group operation aggregationOperation // aggregation type @@ -43,7 +42,7 @@ type aggregator struct { // empty groupBy indicates no grouping. All values are aggregated into a single group. // TODO: add without argument to support `without(...)` grouping. // A special case of `without()` that has empty groupBy is used for Noop grouping which retains the input labels as is. -func newAggregator(groupBy []physical.ColumnExpression, pointsSizeHint int, operation aggregationOperation) *aggregator { +func newAggregator(groupBy []*physicalpb.ColumnExpression, pointsSizeHint int, operation aggregationOperation) *aggregator { a := aggregator{ groupBy: groupBy, digest: xxhash.New(), @@ -140,11 +139,7 @@ func (a *aggregator) BuildRecord() (arrow.Record, error) { ) for _, column := range a.groupBy { - colExpr, ok := column.(*physical.ColumnExpr) - if !ok { - panic(fmt.Sprintf("invalid column expression type %T", column)) - } - ident := semconv.NewIdentifier(colExpr.Ref.Column, colExpr.Ref.Type, types.Loki.String) + ident := semconv.NewIdentifier(column.Name, column.Type, types.Loki.String) fields = append(fields, semconv.FieldFromIdent(ident, true)) } diff --git a/pkg/engine/internal/executor/aggregator_test.go b/pkg/engine/internal/executor/aggregator_test.go index bf28af0adea3c..78cce980fa88d 100644 --- a/pkg/engine/internal/executor/aggregator_test.go +++ b/pkg/engine/internal/executor/aggregator_test.go @@ -6,25 +6,21 @@ import ( "github.com/stretchr/testify/require" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/util/arrowtest" ) var ( - groupBy = []physical.ColumnExpression{ - &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "env", - Type: types.ColumnTypeLabel, - }, + groupBy = []*physicalpb.ColumnExpression{ + { + Name: "env", + Type: physicalpb.COLUMN_TYPE_LABEL, }, - &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "service", - Type: types.ColumnTypeLabel, - }, + { + Name: "service", + Type: physicalpb.COLUMN_TYPE_LABEL, }, } ) @@ -32,8 +28,8 @@ var ( func TestAggregator(t *testing.T) { colTs := semconv.ColumnIdentTimestamp.FQN() colVal := semconv.ColumnIdentValue.FQN() - colEnv := semconv.NewIdentifier("env", types.ColumnTypeLabel, types.Loki.String).FQN() - colSvc := semconv.NewIdentifier("service", types.ColumnTypeLabel, types.Loki.String).FQN() + colEnv := semconv.NewIdentifier("env", physicalpb.COLUMN_TYPE_LABEL, types.Loki.String).FQN() + colSvc := semconv.NewIdentifier("service", physicalpb.COLUMN_TYPE_LABEL, types.Loki.String).FQN() t.Run("basic SUM aggregation with record building", func(t *testing.T) { agg := newAggregator(groupBy, 10, aggregationOperationSum) @@ -210,7 +206,7 @@ func TestAggregator(t *testing.T) { t.Run("SUM aggregation with empty groupBy", func(t *testing.T) { // Empty groupBy represents sum by () or sum(...) - all values aggregated into single group - groupBy := []physical.ColumnExpression{} + groupBy := []*physicalpb.ColumnExpression{} agg := newAggregator(groupBy, 1, aggregationOperationSum) diff --git a/pkg/engine/internal/executor/cast.go b/pkg/engine/internal/executor/cast.go index 1b1021165b262..1cd9e01a00992 100644 --- a/pkg/engine/internal/executor/cast.go +++ b/pkg/engine/internal/executor/cast.go @@ -10,11 +10,12 @@ import ( "github.com/apache/arrow-go/v18/arrow/memory" "github.com/dustin/go-humanize" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) -func castFn(operation types.UnaryOp) UnaryFunction { +func castFn(operation physicalpb.UnaryOp) UnaryFunction { return UnaryFunc(func(input arrow.Array) (arrow.Array, error) { sourceCol, ok := input.(*array.String) if !ok { @@ -36,11 +37,11 @@ func castFn(operation types.UnaryOp) UnaryFunction { type conversionFn func(value string) (float64, error) -func getConversionFunction(operation types.UnaryOp) conversionFn { +func getConversionFunction(operation physicalpb.UnaryOp) conversionFn { switch operation { - case types.UnaryOpCastBytes: + case physicalpb.UNARY_OP_CAST_BYTES: return convertBytes - case types.UnaryOpCastDuration: + case physicalpb.UNARY_OP_CAST_DURATION: return convertDuration default: return convertFloat diff --git a/pkg/engine/internal/executor/column.go b/pkg/engine/internal/executor/column.go index 001a8314a4aa3..62041d58d9b4d 100644 --- a/pkg/engine/internal/executor/column.go +++ b/pkg/engine/internal/executor/column.go @@ -7,11 +7,26 @@ import ( "github.com/apache/arrow-go/v18/arrow/array" "github.com/apache/arrow-go/v18/arrow/memory" - "github.com/grafana/loki/v3/pkg/engine/internal/types" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" ) -func NewScalar(value types.Literal, rows int) arrow.Array { - builder := array.NewBuilder(memory.DefaultAllocator, value.Type().ArrowType()) +func NewScalar(value physicalpb.LiteralExpression, rows int) arrow.Array { + var tmp arrow.DataType + switch value.Kind.(type) { + case *physicalpb.LiteralExpression_NullLiteral: + tmp = arrow.Null + case *physicalpb.LiteralExpression_BoolLiteral: + tmp = arrow.FixedWidthTypes.Boolean + case *physicalpb.LiteralExpression_StringLiteral: + tmp = arrow.BinaryTypes.String + case *physicalpb.LiteralExpression_IntegerLiteral, *physicalpb.LiteralExpression_DurationLiteral, *physicalpb.LiteralExpression_BytesLiteral: + tmp = arrow.PrimitiveTypes.Int64 + case *physicalpb.LiteralExpression_FloatLiteral: + tmp = arrow.PrimitiveTypes.Float64 + case *physicalpb.LiteralExpression_TimestampLiteral: + tmp = arrow.FixedWidthTypes.Timestamp_ns + } + builder := array.NewBuilder(memory.DefaultAllocator, tmp) switch builder := builder.(type) { case *array.NullBuilder: @@ -19,35 +34,35 @@ func NewScalar(value types.Literal, rows int) arrow.Array { builder.AppendNull() } case *array.BooleanBuilder: - value := value.Any().(bool) + value := value.GetBoolLiteral().Value for range rows { builder.Append(value) } case *array.StringBuilder: - value := value.Any().(string) + value := value.GetStringLiteral().Value for range rows { builder.Append(value) } case *array.Int64Builder: var v int64 - switch value.Type() { - case types.Loki.Integer: - v = value.Any().(int64) - case types.Loki.Duration: - v = int64(value.Any().(types.Duration)) - case types.Loki.Bytes: - v = int64(value.Any().(types.Bytes)) + switch value.Kind.(type) { + case *physicalpb.LiteralExpression_IntegerLiteral: + v = value.GetIntegerLiteral().Value + case *physicalpb.LiteralExpression_DurationLiteral: + v = value.GetDurationLiteral().Value + case *physicalpb.LiteralExpression_BytesLiteral: + v = value.GetBytesLiteral().Value } for range rows { builder.Append(v) } case *array.Float64Builder: - value := value.Any().(float64) + value := value.GetFloatLiteral().Value for range rows { builder.Append(value) } case *array.TimestampBuilder: - value := value.Any().(types.Timestamp) + value := value.GetTimestampLiteral().Value for range rows { builder.Append(arrow.Timestamp(value)) } @@ -65,7 +80,7 @@ func NewCoalesce(columns []*columnWithType) arrow.Array { // Sort columns by precedence slices.SortFunc(columns, func(a, b *columnWithType) int { - return types.ColumnTypePrecedence(a.ct) - types.ColumnTypePrecedence(b.ct) + return physicalpb.ColumnTypePrecedence(a.ct) - physicalpb.ColumnTypePrecedence(b.ct) }) // Only string columns are supported diff --git a/pkg/engine/internal/executor/compat.go b/pkg/engine/internal/executor/compat.go index 454df64ab8c80..bf74caba8599a 100644 --- a/pkg/engine/internal/executor/compat.go +++ b/pkg/engine/internal/executor/compat.go @@ -9,11 +9,11 @@ import ( "github.com/apache/arrow-go/v18/arrow/array" "github.com/apache/arrow-go/v18/arrow/memory" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" ) -func newColumnCompatibilityPipeline(compat *physical.ColumnCompat, input Pipeline) Pipeline { +func newColumnCompatibilityPipeline(compat *physicalpb.ColumnCompat, input Pipeline) Pipeline { const extracted = "_extracted" return newGenericPipeline(func(ctx context.Context, inputs []Pipeline) (arrow.Record, error) { @@ -45,10 +45,10 @@ func newColumnCompatibilityPipeline(compat *physical.ColumnCompat, input Pipelin return nil, err } switch ident.ColumnType() { - case compat.Collision: + case semconv.ColumnTypePhysToLog(compat.Collision): collisionFieldIndices = append(collisionFieldIndices, idx) collisionFieldNames = append(collisionFieldNames, ident.ShortName()) - case compat.Source: + case semconv.ColumnTypePhysToLog(compat.Source): sourceFieldIndices = append(sourceFieldIndices, idx) sourceFieldNames = append(sourceFieldNames, ident.ShortName()) } diff --git a/pkg/engine/internal/executor/compat_test.go b/pkg/engine/internal/executor/compat_test.go index 0f61f4044cc28..3601a4f3093a3 100644 --- a/pkg/engine/internal/executor/compat_test.go +++ b/pkg/engine/internal/executor/compat_test.go @@ -11,7 +11,7 @@ import ( "github.com/apache/arrow-go/v18/arrow/memory" "github.com/stretchr/testify/require" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/util/arrowtest" @@ -172,7 +172,7 @@ func sortDuplicatesByValue(duplicates []duplicate) { func TestNewColumnCompatibilityPipeline(t *testing.T) { tests := []struct { name string - compat *physical.ColumnCompat + compat *physicalpb.ColumnCompat schema *arrow.Schema inputRows []arrowtest.Rows expectedSchema *arrow.Schema @@ -182,10 +182,10 @@ func TestNewColumnCompatibilityPipeline(t *testing.T) { }{ { name: "no column collisions - returns early", - compat: &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat: &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, }, schema: arrow.NewSchema([]arrow.Field{ semconv.FieldFromFQN("utf8.builtin.message", true), @@ -214,10 +214,10 @@ func TestNewColumnCompatibilityPipeline(t *testing.T) { }, { name: "single column collision - string type", - compat: &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat: &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, }, schema: arrow.NewSchema([]arrow.Field{ semconv.FieldFromFQN("utf8.builtin.message", true), @@ -247,10 +247,10 @@ func TestNewColumnCompatibilityPipeline(t *testing.T) { }, { name: "multiple column collisions", - compat: &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat: &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, }, schema: arrow.NewSchema([]arrow.Field{ semconv.FieldFromFQN("utf8.builtin.message", true), @@ -299,10 +299,10 @@ func TestNewColumnCompatibilityPipeline(t *testing.T) { }, { name: "collision with null values in collision column", - compat: &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat: &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, }, schema: arrow.NewSchema([]arrow.Field{ semconv.FieldFromFQN("utf8.label.status", true), @@ -332,10 +332,10 @@ func TestNewColumnCompatibilityPipeline(t *testing.T) { }, { name: "collision with null values in source column", - compat: &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat: &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, }, schema: arrow.NewSchema([]arrow.Field{ semconv.FieldFromFQN("utf8.label.status", true), @@ -359,10 +359,10 @@ func TestNewColumnCompatibilityPipeline(t *testing.T) { }, { name: "multiple batches with collisions", - compat: &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat: &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, }, schema: arrow.NewSchema([]arrow.Field{ semconv.FieldFromFQN("utf8.label.status", true), @@ -394,10 +394,10 @@ func TestNewColumnCompatibilityPipeline(t *testing.T) { }, { name: "empty batch does not add _extracted column", - compat: &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat: &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, }, schema: arrow.NewSchema([]arrow.Field{ semconv.FieldFromFQN("utf8.label.status", true), @@ -416,10 +416,10 @@ func TestNewColumnCompatibilityPipeline(t *testing.T) { }, { name: "non-string column types - should copy through unchanged", - compat: &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat: &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, }, schema: arrow.NewSchema([]arrow.Field{ semconv.FieldFromFQN("utf8.builtin.message", true), @@ -536,10 +536,10 @@ func TestNewColumnCompatibilityPipeline(t *testing.T) { func TestNewColumnCompatibilityPipeline_ErrorCases(t *testing.T) { t.Run("invalid field name in schema", func(t *testing.T) { - compat := &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat := &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, } // Create schema with invalid field name that cannot be parsed by semconv.ParseFQN @@ -560,10 +560,10 @@ func TestNewColumnCompatibilityPipeline_ErrorCases(t *testing.T) { }) t.Run("input pipeline error", func(t *testing.T) { - compat := &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat := &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, } // Create a pipeline that will return an expected error @@ -578,10 +578,10 @@ func TestNewColumnCompatibilityPipeline_ErrorCases(t *testing.T) { }) t.Run("non-string collision column should panic", func(t *testing.T) { - compat := &physical.ColumnCompat{ - Collision: types.ColumnTypeLabel, - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, + compat := &physicalpb.ColumnCompat{ + Collision: physicalpb.COLUMN_TYPE_LABEL, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, } // Create schema where source column is not string type diff --git a/pkg/engine/internal/executor/dataobjscan.go b/pkg/engine/internal/executor/dataobjscan.go index be2717be43582..1cd181a1e1438 100644 --- a/pkg/engine/internal/executor/dataobjscan.go +++ b/pkg/engine/internal/executor/dataobjscan.go @@ -16,7 +16,7 @@ import ( "github.com/grafana/loki/v3/pkg/dataobj/sections/logs" "github.com/grafana/loki/v3/pkg/dataobj/sections/streams" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) @@ -24,9 +24,9 @@ import ( type dataobjScanOptions struct { StreamsSection *streams.Section LogsSection *logs.Section - StreamIDs []int64 // Stream IDs to match from logs sections. - Predicates []logs.Predicate // Predicate to apply to the logs. - Projections []physical.ColumnExpression // Columns to include. An empty slice means all columns. + StreamIDs []int64 // Stream IDs to match from logs sections. + Predicates []logs.Predicate // Predicate to apply to the logs. + Projections []*physicalpb.ColumnExpression // Columns to include. An empty slice means all columns. BatchSize int64 // The buffer size for reading rows, derived from the engine batch size. } @@ -115,7 +115,7 @@ func (s *dataobjScan) initStreams() error { // If projections is non-empty but contains no references to labels or // ambiguous columns, projectedLabelColumns returns nil to indicate that no // label columns are needed. -func projectedLabelColumns(sec *streams.Section, projections []physical.ColumnExpression) []*streams.Column { +func projectedLabelColumns(sec *streams.Section, projections []*physicalpb.ColumnExpression) []*streams.Column { var found []*streams.Column // Special case: if projections is empty, we return all label columns. While @@ -134,14 +134,9 @@ func projectedLabelColumns(sec *streams.Section, projections []physical.ColumnEx // Inefficient search. Will we have enough columns + projections such that // this needs to be optimized? for _, projection := range projections { - expr, ok := projection.(*physical.ColumnExpr) - if !ok { - panic("invalid projection type, expected *physical.ColumnExpr") - } - // We're loading the sterams section for joining stream labels into // records, so we only need to consider label and ambiguous columns here. - if expr.Ref.Type != types.ColumnTypeLabel && expr.Ref.Type != types.ColumnTypeAmbiguous { + if projection.Type != physicalpb.COLUMN_TYPE_LABEL && projection.Type != physicalpb.COLUMN_TYPE_AMBIGUOUS { continue } @@ -150,7 +145,7 @@ func projectedLabelColumns(sec *streams.Section, projections []physical.ColumnEx continue } - if col.Name == expr.Ref.Column { + if col.Name == projection.Name { found = append(found, col) break } @@ -250,7 +245,7 @@ func logsColumnToEngineField(col *logs.Column) (arrow.Field, error) { return semconv.FieldFromIdent(semconv.ColumnIdentMessage, true), nil case logs.ColumnTypeMetadata: - return semconv.FieldFromIdent(semconv.NewIdentifier(col.Name, types.ColumnTypeMetadata, types.Loki.String), true), nil + return semconv.FieldFromIdent(semconv.NewIdentifier(col.Name, physicalpb.COLUMN_TYPE_METADATA, types.Loki.String), true), nil } return arrow.Field{}, fmt.Errorf("unsupported logs column type %s", col.Type) @@ -274,7 +269,7 @@ var logsColumnPrecedence = map[logs.ColumnType]int{ // // projectedLogsColumns never includes the stream ID column in its results, as // projections can never reference a stream ID column. -func projectedLogsColumns(sec *logs.Section, projections []physical.ColumnExpression) []*logs.Column { +func projectedLogsColumns(sec *logs.Section, projections []*physicalpb.ColumnExpression) []*logs.Column { var found []*logs.Column defer func() { @@ -308,32 +303,28 @@ func projectedLogsColumns(sec *logs.Section, projections []physical.ColumnExpres // this needs to be optimized? NextProjection: for _, projection := range projections { - expr, ok := projection.(*physical.ColumnExpr) - if !ok { - panic("invalid projection type, expected *physical.ColumnExpr") - } // Ignore columns that cannot exist in the logs section. - switch expr.Ref.Type { - case types.ColumnTypeLabel, types.ColumnTypeParsed, types.ColumnTypeGenerated: + switch projection.Type { + case physicalpb.COLUMN_TYPE_LABEL, physicalpb.COLUMN_TYPE_PARSED, physicalpb.COLUMN_TYPE_GENERATED: continue NextProjection } for _, col := range sec.Columns() { switch { - case expr.Ref.Type == types.ColumnTypeBuiltin && expr.Ref.Column == types.ColumnNameBuiltinTimestamp && col.Type == logs.ColumnTypeTimestamp: + case projection.Type == physicalpb.COLUMN_TYPE_BUILTIN && projection.Name == types.ColumnNameBuiltinTimestamp && col.Type == logs.ColumnTypeTimestamp: found = append(found, col) continue NextProjection - case expr.Ref.Type == types.ColumnTypeBuiltin && expr.Ref.Column == types.ColumnNameBuiltinMessage && col.Type == logs.ColumnTypeMessage: + case projection.Type == physicalpb.COLUMN_TYPE_BUILTIN && projection.Name == types.ColumnNameBuiltinMessage && col.Type == logs.ColumnTypeMessage: found = append(found, col) continue NextProjection - case expr.Ref.Type == types.ColumnTypeMetadata && col.Type == logs.ColumnTypeMetadata && col.Name == expr.Ref.Column: + case projection.Type == physicalpb.COLUMN_TYPE_METADATA && col.Type == logs.ColumnTypeMetadata && col.Name == projection.Name: found = append(found, col) continue NextProjection - case expr.Ref.Type == types.ColumnTypeAmbiguous && col.Type == logs.ColumnTypeMetadata && col.Name == expr.Ref.Column: + case projection.Type == physicalpb.COLUMN_TYPE_AMBIGUOUS && col.Type == logs.ColumnTypeMetadata && col.Name == projection.Name: found = append(found, col) continue NextProjection } diff --git a/pkg/engine/internal/executor/dataobjscan_predicate.go b/pkg/engine/internal/executor/dataobjscan_predicate.go index e46936f3e1583..600434de52dbf 100644 --- a/pkg/engine/internal/executor/dataobjscan_predicate.go +++ b/pkg/engine/internal/executor/dataobjscan_predicate.go @@ -10,7 +10,7 @@ import ( "github.com/apache/arrow-go/v18/arrow/scalar" "github.com/grafana/loki/v3/pkg/dataobj/sections/logs" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) @@ -28,24 +28,25 @@ import ( // - Expressions cannot be represented as a boolean value // - An expression is not supported (such as comparing two columns or comparing // two literals). -func buildLogsPredicate(expr physical.Expression, columns []*logs.Column) (logs.Predicate, error) { - switch expr := expr.(type) { - case physical.UnaryExpression: - return buildLogsUnaryPredicate(expr, columns) - - case physical.BinaryExpression: - return buildLogsBinaryPredicate(expr, columns) - - case *physical.LiteralExpr: - if expr.Literal.Type() == types.Loki.Bool { - val := expr.Literal.(types.TypedLiteral[bool]).Value() +func buildLogsPredicate(expr physicalpb.Expression, columns []*logs.Column) (logs.Predicate, error) { + switch expr := expr.Kind.(type) { + case *physicalpb.Expression_UnaryExpression: + return buildLogsUnaryPredicate(*expr.UnaryExpression, columns) + + case *physicalpb.Expression_BinaryExpression: + return buildLogsBinaryPredicate(*expr.BinaryExpression, columns) + + case *physicalpb.Expression_LiteralExpression: + switch (expr.LiteralExpression.Kind).(type) { + case *physicalpb.LiteralExpression_BoolLiteral: + val := expr.LiteralExpression.GetBoolLiteral().Value if val { return logs.TruePredicate{}, nil } return logs.FalsePredicate{}, nil } - case *physical.ColumnExpr: + case *physicalpb.Expression_ColumnExpression: // TODO(rfratto): This would add support for statements like // // SELECT * WHERE boolean_column @@ -66,78 +67,68 @@ func buildLogsPredicate(expr physical.Expression, columns []*logs.Column) (logs. return nil, fmt.Errorf("expression %[1]s (type %[1]T) cannot be interpreted as a boolean", expr) } -func buildLogsUnaryPredicate(expr physical.UnaryExpression, columns []*logs.Column) (logs.Predicate, error) { - unaryExpr, ok := expr.(*physical.UnaryExpr) - if !ok { - return nil, fmt.Errorf("expected physical.UnaryExpr, got %[1]T", expr) - } - - inner, err := buildLogsPredicate(unaryExpr.Left, columns) +func buildLogsUnaryPredicate(expr physicalpb.UnaryExpression, columns []*logs.Column) (logs.Predicate, error) { + inner, err := buildLogsPredicate(*expr.Value, columns) if err != nil { return nil, fmt.Errorf("building unary predicate: %w", err) } - switch unaryExpr.Op { - case types.UnaryOpNot: + switch expr.Op { + case physicalpb.UNARY_OP_NOT: return logs.NotPredicate{Inner: inner}, nil } - return nil, fmt.Errorf("unsupported unary operator %s in logs predicate", unaryExpr.Op) + return nil, fmt.Errorf("unsupported unary operator %s in logs predicate", expr.Op) } -var comparisonBinaryOps = map[types.BinaryOp]struct{}{ - types.BinaryOpEq: {}, - types.BinaryOpNeq: {}, - types.BinaryOpGt: {}, - types.BinaryOpGte: {}, - types.BinaryOpLt: {}, - types.BinaryOpLte: {}, - types.BinaryOpMatchSubstr: {}, - types.BinaryOpNotMatchSubstr: {}, - types.BinaryOpMatchRe: {}, - types.BinaryOpNotMatchRe: {}, - types.BinaryOpMatchPattern: {}, - types.BinaryOpNotMatchPattern: {}, +var comparisonBinaryOps = map[physicalpb.BinaryOp]struct{}{ + physicalpb.BINARY_OP_EQ: {}, + physicalpb.BINARY_OP_NEQ: {}, + physicalpb.BINARY_OP_GT: {}, + physicalpb.BINARY_OP_GTE: {}, + physicalpb.BINARY_OP_LT: {}, + physicalpb.BINARY_OP_LTE: {}, + physicalpb.BINARY_OP_MATCH_SUBSTR: {}, + physicalpb.BINARY_OP_NOT_MATCH_SUBSTR: {}, + physicalpb.BINARY_OP_MATCH_RE: {}, + physicalpb.BINARY_OP_NOT_MATCH_RE: {}, + physicalpb.BINARY_OP_MATCH_PATTERN: {}, + physicalpb.BINARY_OP_NOT_MATCH_PATTERN: {}, } -func buildLogsBinaryPredicate(expr physical.BinaryExpression, columns []*logs.Column) (logs.Predicate, error) { - binaryExpr, ok := expr.(*physical.BinaryExpr) - if !ok { - return nil, fmt.Errorf("expected physical.BinaryExpr, got %[1]T", expr) - } - - switch binaryExpr.Op { - case types.BinaryOpAnd: - left, err := buildLogsPredicate(binaryExpr.Left, columns) +func buildLogsBinaryPredicate(expr physicalpb.BinaryExpression, columns []*logs.Column) (logs.Predicate, error) { + switch expr.Op { + case physicalpb.BINARY_OP_AND: + left, err := buildLogsPredicate(*expr.Left, columns) if err != nil { return nil, fmt.Errorf("building left binary predicate: %w", err) } - right, err := buildLogsPredicate(binaryExpr.Right, columns) + right, err := buildLogsPredicate(*expr.Right, columns) if err != nil { return nil, fmt.Errorf("building right binary predicate: %w", err) } return logs.AndPredicate{Left: left, Right: right}, nil - case types.BinaryOpOr: - left, err := buildLogsPredicate(binaryExpr.Left, columns) + case physicalpb.BINARY_OP_OR: + left, err := buildLogsPredicate(*expr.Left, columns) if err != nil { return nil, fmt.Errorf("building left binary predicate: %w", err) } - right, err := buildLogsPredicate(binaryExpr.Right, columns) + right, err := buildLogsPredicate(*expr.Right, columns) if err != nil { return nil, fmt.Errorf("building right binary predicate: %w", err) } return logs.OrPredicate{Left: left, Right: right}, nil } - if _, ok := comparisonBinaryOps[binaryExpr.Op]; ok { - return buildLogsComparison(binaryExpr, columns) + if _, ok := comparisonBinaryOps[expr.Op]; ok { + return buildLogsComparison(&expr, columns) } return nil, fmt.Errorf("expression %[1]s (type %[1]T) cannot be interpreted as a boolean", expr) } -func buildLogsComparison(expr *physical.BinaryExpr, columns []*logs.Column) (logs.Predicate, error) { +func buildLogsComparison(expr *physicalpb.BinaryExpression, columns []*logs.Column) (logs.Predicate, error) { // Currently, we only support comparisons where the left-hand side is a // [physical.ColumnExpr] and the right-hand side is a [physical.LiteralExpr]. // @@ -150,8 +141,8 @@ func buildLogsComparison(expr *physical.BinaryExpr, columns []*logs.Column) (log // * LHS ColumnExpr, RHS ColumnExpr could be supported in the future, but would need // support down to the dataset level. - columnRef, leftValid := expr.Left.(*physical.ColumnExpr) - literalExpr, rightValid := expr.Right.(*physical.LiteralExpr) + columnRef, leftValid := expr.Left.Kind.(*physicalpb.Expression_ColumnExpression) + literalExpr, rightValid := expr.Right.Kind.(*physicalpb.Expression_LiteralExpression) if !leftValid || !rightValid { return nil, fmt.Errorf("binary comparisons require the left-hand operation to reference a column (got %T) and the right-hand operation to be a literal (got %T)", expr.Left, expr.Right) @@ -160,18 +151,18 @@ func buildLogsComparison(expr *physical.BinaryExpr, columns []*logs.Column) (log // findColumn may return nil for col if the referenced column doesn't exist; // this is handled in the switch statement below and converts to either // [logs.FalsePredicate] or [logs.TruePredicate] depending on the operation. - col, err := findColumn(columnRef.Ref, columns) + col, err := findColumn(*columnRef.ColumnExpression, columns) if err != nil { - return nil, fmt.Errorf("finding column %s: %w", columnRef.Ref, err) + return nil, fmt.Errorf("finding column %s: %w", columnRef.ColumnExpression, err) } - s, err := buildDataobjScalar(literalExpr.Literal) + s, err := buildDataobjScalar(*literalExpr.LiteralExpression) if err != nil { return nil, err } switch expr.Op { - case types.BinaryOpEq: + case physicalpb.BINARY_OP_EQ: if col == nil && s.IsValid() { return logs.FalsePredicate{}, nil // Column(NULL) == non-null: always fails } else if col == nil && !s.IsValid() { @@ -179,7 +170,7 @@ func buildLogsComparison(expr *physical.BinaryExpr, columns []*logs.Column) (log } return logs.EqualPredicate{Column: col, Value: s}, nil - case types.BinaryOpNeq: + case physicalpb.BINARY_OP_NEQ: if col == nil && s.IsValid() { return logs.TruePredicate{}, nil // Column(NULL) != non-null: always passes } else if col == nil && !s.IsValid() { @@ -187,13 +178,13 @@ func buildLogsComparison(expr *physical.BinaryExpr, columns []*logs.Column) (log } return logs.NotPredicate{Inner: logs.EqualPredicate{Column: col, Value: s}}, nil - case types.BinaryOpGt: + case physicalpb.BINARY_OP_GT: if col == nil { return logs.FalsePredicate{}, nil // Column(NULL) > value: always fails } return logs.GreaterThanPredicate{Column: col, Value: s}, nil - case types.BinaryOpGte: + case physicalpb.BINARY_OP_GTE: if col == nil { return logs.FalsePredicate{}, nil // Column(NULL) >= value: always fails } @@ -202,13 +193,13 @@ func buildLogsComparison(expr *physical.BinaryExpr, columns []*logs.Column) (log Right: logs.EqualPredicate{Column: col, Value: s}, }, nil - case types.BinaryOpLt: + case physicalpb.BINARY_OP_LT: if col == nil { return logs.FalsePredicate{}, nil // Column(NULL) < value: always fails } return logs.LessThanPredicate{Column: col, Value: s}, nil - case types.BinaryOpLte: + case physicalpb.BINARY_OP_LTE: if col == nil { return logs.FalsePredicate{}, nil // Column(NULL) <= value: always fails } @@ -217,13 +208,13 @@ func buildLogsComparison(expr *physical.BinaryExpr, columns []*logs.Column) (log Right: logs.EqualPredicate{Column: col, Value: s}, }, nil - case types.BinaryOpMatchSubstr, types.BinaryOpMatchRe, types.BinaryOpMatchPattern: + case physicalpb.BINARY_OP_MATCH_SUBSTR, physicalpb.BINARY_OP_MATCH_RE, physicalpb.BINARY_OP_MATCH_PATTERN: if col == nil { return logs.FalsePredicate{}, nil // Match operations against a non-existent column will always fail. } return buildLogsMatch(col, expr.Op, s) - case types.BinaryOpNotMatchSubstr, types.BinaryOpNotMatchRe, types.BinaryOpNotMatchPattern: + case physicalpb.BINARY_OP_NOT_MATCH_SUBSTR, physicalpb.BINARY_OP_NOT_MATCH_RE, physicalpb.BINARY_OP_NOT_MATCH_PATTERN: if col == nil { return logs.TruePredicate{}, nil // Not match operations against a non-existent column will always pass. } @@ -236,19 +227,19 @@ func buildLogsComparison(expr *physical.BinaryExpr, columns []*logs.Column) (log // findColumn finds a column by ref in the slice of columns. If ref is invalid, // findColumn returns an error. If the column does not exist, findColumn // returns nil. -func findColumn(ref types.ColumnRef, columns []*logs.Column) (*logs.Column, error) { - if ref.Type != types.ColumnTypeBuiltin && ref.Type != types.ColumnTypeMetadata && ref.Type != types.ColumnTypeAmbiguous { +func findColumn(ref physicalpb.ColumnExpression, columns []*logs.Column) (*logs.Column, error) { + if ref.Type != physicalpb.COLUMN_TYPE_BUILTIN && ref.Type != physicalpb.COLUMN_TYPE_METADATA && ref.Type != physicalpb.COLUMN_TYPE_AMBIGUOUS { return nil, fmt.Errorf("invalid column ref %s, expected builtin or metadata", ref) } - columnMatch := func(ref types.ColumnRef, column *logs.Column) bool { + columnMatch := func(ref physicalpb.ColumnExpression, column *logs.Column) bool { switch { - case ref.Type == types.ColumnTypeBuiltin && ref.Column == types.ColumnNameBuiltinTimestamp: + case ref.Type == physicalpb.COLUMN_TYPE_BUILTIN && ref.Name == types.ColumnNameBuiltinTimestamp: return column.Type == logs.ColumnTypeTimestamp - case ref.Type == types.ColumnTypeBuiltin && ref.Column == types.ColumnNameBuiltinMessage: + case ref.Type == physicalpb.COLUMN_TYPE_BUILTIN && ref.Name == types.ColumnNameBuiltinMessage: return column.Type == logs.ColumnTypeMessage - case ref.Type == types.ColumnTypeMetadata || ref.Type == types.ColumnTypeAmbiguous: - return column.Name == ref.Column + case ref.Type == physicalpb.COLUMN_TYPE_METADATA || ref.Type == physicalpb.COLUMN_TYPE_AMBIGUOUS: + return column.Name == ref.Name } return false @@ -265,7 +256,7 @@ func findColumn(ref types.ColumnRef, columns []*logs.Column) (*logs.Column, erro // buildDataobjScalar builds a dataobj-compatible [scalar.Scalar] from a // [types.Literal]. -func buildDataobjScalar(lit types.Literal) (scalar.Scalar, error) { +func buildDataobjScalar(lit physicalpb.LiteralExpression) (scalar.Scalar, error) { // [logs.ReaderOptions.Validate] specifies that all scalars must be one of // the given types: // @@ -277,27 +268,27 @@ func buildDataobjScalar(lit types.Literal) (scalar.Scalar, error) { // // All of our mappings below evaluate to one of the above types. - switch lit := lit.(type) { - case types.NullLiteral: + switch lit := lit.Kind.(type) { + case *physicalpb.LiteralExpression_NullLiteral: return scalar.ScalarNull, nil - case types.IntegerLiteral: - return scalar.NewInt64Scalar(lit.Value()), nil - case types.BytesLiteral: + case *physicalpb.LiteralExpression_IntegerLiteral: + return scalar.NewInt64Scalar(lit.IntegerLiteral.Value), nil + case *physicalpb.LiteralExpression_BytesLiteral: // [types.BytesLiteral] refers to byte sizes, not binary data. - return scalar.NewInt64Scalar(int64(lit.Value())), nil - case types.TimestampLiteral: - ts := arrow.Timestamp(lit.Value()) + return scalar.NewInt64Scalar(lit.BytesLiteral.Value), nil + case *physicalpb.LiteralExpression_TimestampLiteral: + ts := arrow.Timestamp(lit.TimestampLiteral.Value) tsType := arrow.FixedWidthTypes.Timestamp_ns return scalar.NewTimestampScalar(ts, tsType), nil - case types.StringLiteral: - buf := memory.NewBufferBytes([]byte(lit.Value())) + case *physicalpb.LiteralExpression_StringLiteral: + buf := memory.NewBufferBytes([]byte(lit.StringLiteral.Value)) return scalar.NewBinaryScalar(buf, arrow.BinaryTypes.Binary), nil } return nil, fmt.Errorf("unsupported literal type %T", lit) } -func buildLogsMatch(col *logs.Column, op types.BinaryOp, value scalar.Scalar) (logs.Predicate, error) { +func buildLogsMatch(col *logs.Column, op physicalpb.BinaryOp, value scalar.Scalar) (logs.Predicate, error) { // All the match operations require the value to be a string or a binary. var find []byte @@ -311,7 +302,7 @@ func buildLogsMatch(col *logs.Column, op types.BinaryOp, value scalar.Scalar) (l } switch op { - case types.BinaryOpMatchSubstr: + case physicalpb.BINARY_OP_MATCH_SUBSTR: return logs.FuncPredicate{ Column: col, Keep: func(_ *logs.Column, value scalar.Scalar) bool { @@ -319,7 +310,7 @@ func buildLogsMatch(col *logs.Column, op types.BinaryOp, value scalar.Scalar) (l }, }, nil - case types.BinaryOpNotMatchSubstr: + case physicalpb.BINARY_OP_NOT_MATCH_SUBSTR: return logs.FuncPredicate{ Column: col, Keep: func(_ *logs.Column, value scalar.Scalar) bool { @@ -327,7 +318,7 @@ func buildLogsMatch(col *logs.Column, op types.BinaryOp, value scalar.Scalar) (l }, }, nil - case types.BinaryOpMatchRe: + case physicalpb.BINARY_OP_MATCH_RE: re, err := regexp.Compile(string(find)) if err != nil { return nil, err @@ -339,7 +330,7 @@ func buildLogsMatch(col *logs.Column, op types.BinaryOp, value scalar.Scalar) (l }, }, nil - case types.BinaryOpNotMatchRe: + case physicalpb.BINARY_OP_NOT_MATCH_RE: re, err := regexp.Compile(string(find)) if err != nil { return nil, err @@ -352,7 +343,7 @@ func buildLogsMatch(col *logs.Column, op types.BinaryOp, value scalar.Scalar) (l }, nil } - // NOTE(rfratto): [types.BinaryOpMatchPattern] and [types.BinaryOpNotMatchPattern] + // NOTE(rfratto): [physicalpb.BINARY_OP_MATCH_PATTERN] and [physicalpb.BINARY_OP_NOT_MATCH_PATTERN] // are currently unsupported. return nil, fmt.Errorf("unrecognized match operation %s", op) } diff --git a/pkg/engine/internal/executor/dataobjscan_predicate_test.go b/pkg/engine/internal/executor/dataobjscan_predicate_test.go index 218adf054217c..76f1e50aed719 100644 --- a/pkg/engine/internal/executor/dataobjscan_predicate_test.go +++ b/pkg/engine/internal/executor/dataobjscan_predicate_test.go @@ -10,6 +10,7 @@ import ( "github.com/grafana/loki/v3/pkg/dataobj/sections/logs" "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) @@ -27,26 +28,26 @@ func Test_buildLogsPredicate(t *testing.T) { tt := []struct { name string - expr physical.Expression + expr physicalpb.Expression expect logs.Predicate }{ { name: "literal true", - expr: physical.NewLiteral(true), + expr: *physical.NewLiteral(true).ToExpression(), expect: logs.TruePredicate{}, }, { name: "literal false", - expr: physical.NewLiteral(false), + expr: *physical.NewLiteral(false).ToExpression(), expect: logs.FalsePredicate{}, }, { name: "unary NOT", - expr: &physical.UnaryExpr{ - Op: types.UnaryOpNot, - Left: physical.NewLiteral(false), - }, + expr: *(&physicalpb.UnaryExpression{ + Op: physicalpb.UNARY_OP_NOT, + Value: physical.NewLiteral(false).ToExpression(), + }).ToExpression(), expect: logs.NotPredicate{ Inner: logs.FalsePredicate{}, }, @@ -54,11 +55,11 @@ func Test_buildLogsPredicate(t *testing.T) { { name: "binary AND", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpAnd, - Left: physical.NewLiteral(true), - Right: physical.NewLiteral(false), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_AND, + Left: physical.NewLiteral(true).ToExpression(), + Right: physical.NewLiteral(false).ToExpression(), + }).ToExpression(), expect: logs.AndPredicate{ Left: logs.TruePredicate{}, Right: logs.FalsePredicate{}, @@ -66,24 +67,23 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "binary OR", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpOr, - Left: physical.NewLiteral(true), - Right: physical.NewLiteral(false), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_OR, + Left: physical.NewLiteral(true).ToExpression(), + Right: physical.NewLiteral(false).ToExpression(), + }).ToExpression(), expect: logs.OrPredicate{ Left: logs.TruePredicate{}, Right: logs.FalsePredicate{}, }, }, - { name: "builtin timestamp reference", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeBuiltin, types.ColumnNameBuiltinTimestamp), - Right: physical.NewLiteral(int64(1234567890)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_BUILTIN, types.ColumnNameBuiltinTimestamp).ToExpression(), + Right: physical.NewLiteral(int64(1234567890)).ToExpression(), + }).ToExpression(), expect: logs.EqualPredicate{ Column: timestampColumn, Value: scalar.NewInt64Scalar(1234567890), @@ -91,11 +91,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "builtin message reference", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeBuiltin, types.ColumnNameBuiltinMessage), - Right: physical.NewLiteral(int64(9876543210)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_BUILTIN, types.ColumnNameBuiltinMessage).ToExpression(), + Right: physical.NewLiteral(int64(9876543210)).ToExpression(), + }).ToExpression(), expect: logs.EqualPredicate{ Column: messageColumn, Value: scalar.NewInt64Scalar(9876543210), @@ -103,11 +103,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "metadata reference", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral(int64(5555555555)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral(int64(5555555555)).ToExpression(), + }).ToExpression(), expect: logs.EqualPredicate{ Column: metadataColumn, Value: scalar.NewInt64Scalar(5555555555), @@ -115,11 +115,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "ambiguous metadata reference", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeAmbiguous, "metadata"), - Right: physical.NewLiteral(int64(7777777777)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_AMBIGUOUS, "metadata").ToExpression(), + Right: physical.NewLiteral(int64(7777777777)).ToExpression(), + }).ToExpression(), expect: logs.EqualPredicate{ Column: metadataColumn, Value: scalar.NewInt64Scalar(7777777777), @@ -128,11 +128,11 @@ func Test_buildLogsPredicate(t *testing.T) { { name: "check column for null literal", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeBuiltin, types.ColumnNameBuiltinTimestamp), - Right: physical.NewLiteral(nil), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_BUILTIN, types.ColumnNameBuiltinTimestamp).ToExpression(), + Right: physical.NewLiteral(nil).ToExpression(), + }).ToExpression(), expect: logs.EqualPredicate{ Column: timestampColumn, Value: scalar.ScalarNull, @@ -140,11 +140,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "check column for integer literal", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeBuiltin, types.ColumnNameBuiltinTimestamp), - Right: physical.NewLiteral(int64(42)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_BUILTIN, types.ColumnNameBuiltinTimestamp).ToExpression(), + Right: physical.NewLiteral(int64(42)).ToExpression(), + }).ToExpression(), expect: logs.EqualPredicate{ Column: timestampColumn, Value: scalar.NewInt64Scalar(42), @@ -152,11 +152,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "check column for bytes literal", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeBuiltin, types.ColumnNameBuiltinTimestamp), - Right: physical.NewLiteral(types.Bytes(1024)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_BUILTIN, types.ColumnNameBuiltinTimestamp).ToExpression(), + Right: physical.NewLiteral(types.Bytes(1024)).ToExpression(), + }).ToExpression(), expect: logs.EqualPredicate{ Column: timestampColumn, Value: scalar.NewInt64Scalar(1024), @@ -164,11 +164,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "check column for timestamp literal", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeBuiltin, types.ColumnNameBuiltinTimestamp), - Right: physical.NewLiteral(types.Timestamp(1609459200000000000)), // 2021-01-01 00:00:00 UTC in nanoseconds - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_BUILTIN, types.ColumnNameBuiltinTimestamp).ToExpression(), + Right: physical.NewLiteral(types.Timestamp(1609459200000000000)).ToExpression(), // 2021-01-01 00:00:00 UTC in nanoseconds + }).ToExpression(), expect: logs.EqualPredicate{ Column: timestampColumn, Value: scalar.NewTimestampScalar(arrow.Timestamp(1609459200000000000), arrow.FixedWidthTypes.Timestamp_ns), @@ -176,11 +176,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "check column for string literal", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeBuiltin, types.ColumnNameBuiltinTimestamp), - Right: physical.NewLiteral("hello world"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_BUILTIN, types.ColumnNameBuiltinTimestamp).ToExpression(), + Right: physical.NewLiteral("hello world").ToExpression(), + }).ToExpression(), expect: logs.EqualPredicate{ Column: timestampColumn, Value: scalar.NewBinaryScalar(memory.NewBufferBytes([]byte("hello world")), arrow.BinaryTypes.Binary), @@ -189,11 +189,11 @@ func Test_buildLogsPredicate(t *testing.T) { { name: "binary EQ", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral("test_value"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral("test_value").ToExpression(), + }).ToExpression(), expect: logs.EqualPredicate{ Column: metadataColumn, Value: scalar.NewBinaryScalar(memory.NewBufferBytes([]byte("test_value")), arrow.BinaryTypes.Binary), @@ -201,11 +201,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "binary NEQ", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpNeq, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral("test_value"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_NEQ, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral("test_value").ToExpression(), + }).ToExpression(), expect: logs.NotPredicate{ Inner: logs.EqualPredicate{ Column: metadataColumn, @@ -215,11 +215,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "binary GT", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpGt, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral(int64(100)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_GT, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral(int64(100)).ToExpression(), + }).ToExpression(), expect: logs.GreaterThanPredicate{ Column: metadataColumn, Value: scalar.NewInt64Scalar(100), @@ -227,11 +227,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "binary GTE", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpGte, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral(int64(100)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_GTE, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral(int64(100)).ToExpression(), + }).ToExpression(), expect: logs.OrPredicate{ Left: logs.GreaterThanPredicate{Column: metadataColumn, Value: scalar.NewInt64Scalar(100)}, Right: logs.EqualPredicate{Column: metadataColumn, Value: scalar.NewInt64Scalar(100)}, @@ -239,11 +239,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "binary LT", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpLt, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral(int64(100)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_LT, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral(int64(100)).ToExpression(), + }).ToExpression(), expect: logs.LessThanPredicate{ Column: metadataColumn, Value: scalar.NewInt64Scalar(100), @@ -251,11 +251,11 @@ func Test_buildLogsPredicate(t *testing.T) { }, { name: "binary LTE", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpLte, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral(int64(100)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_LTE, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral(int64(100)).ToExpression(), + }).ToExpression(), expect: logs.OrPredicate{ Left: logs.LessThanPredicate{Column: metadataColumn, Value: scalar.NewInt64Scalar(100)}, Right: logs.EqualPredicate{Column: metadataColumn, Value: scalar.NewInt64Scalar(100)}, @@ -264,117 +264,117 @@ func Test_buildLogsPredicate(t *testing.T) { { name: "binary EQ (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral("test_value"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral("test_value").ToExpression(), + }).ToExpression(), expect: logs.FalsePredicate{}, // non-null value can't equal NULL column }, { name: "binary NEQ (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpNeq, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral("test_value"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_NEQ, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral("test_value").ToExpression(), + }).ToExpression(), expect: logs.TruePredicate{}, // non-null value != NULL column }, { name: "binary EQ NULL (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpEq, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral(nil), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_EQ, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral(nil).ToExpression(), + }).ToExpression(), expect: logs.TruePredicate{}, // NULL == NULL: always passes }, { name: "binary NEQ NULL (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpNeq, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral(nil), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_NEQ, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral(nil).ToExpression(), + }).ToExpression(), expect: logs.FalsePredicate{}, // NULL != NULL: always fails }, { name: "binary GT (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpGt, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral(int64(100)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_GT, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral(int64(100)).ToExpression(), + }).ToExpression(), expect: logs.FalsePredicate{}, // NULL > value always fails }, { name: "binary GTE (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpGte, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral(int64(100)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_GTE, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral(int64(100)).ToExpression(), + }).ToExpression(), expect: logs.FalsePredicate{}, // NULL >= value always fails }, { name: "binary LT (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpLt, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral(int64(100)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_LT, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral(int64(100)).ToExpression(), + }).ToExpression(), expect: logs.FalsePredicate{}, // NULL < value always fails }, { name: "binary LTE (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpLte, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral(int64(100)), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_LTE, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral(int64(100)).ToExpression(), + }).ToExpression(), expect: logs.FalsePredicate{}, // NULL <= value always fails }, { name: "binary MATCH_STR (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpMatchSubstr, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral("substring"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_MATCH_SUBSTR, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral("substring").ToExpression(), + }).ToExpression(), expect: logs.FalsePredicate{}, // match against non-existent column always fails }, { name: "binary NOT_MATCH_STR (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpNotMatchSubstr, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral("substring"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_NOT_MATCH_SUBSTR, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral("substring").ToExpression(), + }).ToExpression(), expect: logs.TruePredicate{}, // not match against non-existent column always passes }, { name: "binary MATCH_RE (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpMatchRe, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral("^test.*"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_MATCH_RE, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral("^test.*").ToExpression(), + }).ToExpression(), expect: logs.FalsePredicate{}, // match against non-existent column always fails }, { name: "binary NOT_MATCH_RE (invalid column)", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpNotMatchRe, - Left: columnRef(types.ColumnTypeMetadata, "nonexistent"), - Right: physical.NewLiteral("^test.*"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_NOT_MATCH_RE, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "nonexistent").ToExpression(), + Right: physical.NewLiteral("^test.*").ToExpression(), + }).ToExpression(), expect: logs.TruePredicate{}, // not match against non-existent column always passes }, } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { - if tc.expr == nil { + if tc.expr.Kind == nil { t.Skip() } @@ -401,17 +401,17 @@ func Test_buildLogsPredicate_FuncPredicates(t *testing.T) { tt := []struct { name string - expr physical.Expression + expr physicalpb.Expression expectedColumn *logs.Column keepTests []keepTest }{ { name: "binary MATCH_STR", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpMatchSubstr, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral("substring"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_MATCH_SUBSTR, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral("substring").ToExpression(), + }).ToExpression(), expectedColumn: metadataColumn, keepTests: []keepTest{ { @@ -442,11 +442,11 @@ func Test_buildLogsPredicate_FuncPredicates(t *testing.T) { }, { name: "binary NOT_MATCH_STR", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpNotMatchSubstr, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral("substring"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_NOT_MATCH_SUBSTR, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral("substring").ToExpression(), + }).ToExpression(), expectedColumn: metadataColumn, keepTests: []keepTest{ { @@ -477,11 +477,11 @@ func Test_buildLogsPredicate_FuncPredicates(t *testing.T) { }, { name: "binary MATCH_RE", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpMatchRe, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral("^test.*"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_MATCH_RE, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral("^test.*").ToExpression(), + }).ToExpression(), expectedColumn: metadataColumn, keepTests: []keepTest{ { @@ -512,11 +512,11 @@ func Test_buildLogsPredicate_FuncPredicates(t *testing.T) { }, { name: "binary NOT_MATCH_RE", - expr: &physical.BinaryExpr{ - Op: types.BinaryOpNotMatchRe, - Left: columnRef(types.ColumnTypeMetadata, "metadata"), - Right: physical.NewLiteral("^test.*"), - }, + expr: *(&physicalpb.BinaryExpression{ + Op: physicalpb.BINARY_OP_NOT_MATCH_RE, + Left: columnRef(physicalpb.COLUMN_TYPE_METADATA, "metadata").ToExpression(), + Right: physical.NewLiteral("^test.*").ToExpression(), + }).ToExpression(), expectedColumn: metadataColumn, keepTests: []keepTest{ { @@ -568,11 +568,9 @@ func Test_buildLogsPredicate_FuncPredicates(t *testing.T) { } } -func columnRef(ty types.ColumnType, column string) *physical.ColumnExpr { - return &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Type: ty, - Column: column, - }, +func columnRef(ty physicalpb.ColumnType, column string) *physicalpb.ColumnExpression { + return &physicalpb.ColumnExpression{ + Type: ty, + Name: column, } } diff --git a/pkg/engine/internal/executor/dataobjscan_test.go b/pkg/engine/internal/executor/dataobjscan_test.go index c3b06a470a754..cce2547285981 100644 --- a/pkg/engine/internal/executor/dataobjscan_test.go +++ b/pkg/engine/internal/executor/dataobjscan_test.go @@ -13,9 +13,8 @@ import ( "github.com/grafana/loki/v3/pkg/dataobj/consumer/logsobj" "github.com/grafana/loki/v3/pkg/dataobj/sections/logs" "github.com/grafana/loki/v3/pkg/dataobj/sections/streams" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" - "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/logproto" "github.com/grafana/loki/pkg/push" @@ -109,9 +108,9 @@ prod,notloki,NULL,notloki-pod-1,1970-01-01 00:00:02,hello world` StreamsSection: streamsSection, LogsSection: logsSection, StreamIDs: []int64{1, 2}, // All streams - Projections: []physical.ColumnExpression{ - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "env", Type: types.ColumnTypeLabel}}, - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "timestamp", Type: types.ColumnTypeBuiltin}}, + Projections: []*physicalpb.ColumnExpression{ + {Name: "env", Type: physicalpb.COLUMN_TYPE_LABEL}, + {Name: "timestamp", Type: physicalpb.COLUMN_TYPE_BUILTIN}, }, BatchSize: 512, @@ -168,8 +167,8 @@ prod,notloki,NULL,notloki-pod-1,1970-01-01 00:00:02,hello world` StreamsSection: streamsSection, LogsSection: logsSection, StreamIDs: []int64{1, 2}, // All streams - Projections: []physical.ColumnExpression{ - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "env", Type: types.ColumnTypeAmbiguous}}, + Projections: []*physicalpb.ColumnExpression{ + {Name: "env", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}, }, BatchSize: 512, }, log.NewNopLogger()) @@ -281,8 +280,8 @@ prod,NULL,pod-1,loki,NULL,override,1970-01-01 00:00:01,message 1` StreamsSection: streamsSection, LogsSection: logsSection, StreamIDs: []int64{1, 2, 3}, // All streams - Projections: []physical.ColumnExpression{ - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "pod", Type: types.ColumnTypeAmbiguous}}, + Projections: []*physicalpb.ColumnExpression{ + {Name: "pod", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}, }, BatchSize: 512, }, log.NewNopLogger()) @@ -307,8 +306,8 @@ pod-1,override` StreamsSection: streamsSection, LogsSection: logsSection, StreamIDs: []int64{1, 2, 3}, // All streams - Projections: []physical.ColumnExpression{ - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "namespace", Type: types.ColumnTypeAmbiguous}}, + Projections: []*physicalpb.ColumnExpression{ + {Name: "namespace", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}, }, BatchSize: 512, }, log.NewNopLogger()) diff --git a/pkg/engine/internal/executor/executor.go b/pkg/engine/internal/executor/executor.go index 1a8de15c2679a..3b1b98e98352f 100644 --- a/pkg/engine/internal/executor/executor.go +++ b/pkg/engine/internal/executor/executor.go @@ -4,8 +4,10 @@ import ( "context" "errors" "fmt" + "time" "github.com/go-kit/log" + "github.com/go-kit/log/level" "github.com/grafana/dskit/user" "github.com/thanos-io/objstore" "go.opentelemetry.io/otel" @@ -15,7 +17,8 @@ import ( "github.com/grafana/loki/v3/pkg/dataobj" "github.com/grafana/loki/v3/pkg/dataobj/sections/logs" "github.com/grafana/loki/v3/pkg/dataobj/sections/streams" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" + "github.com/grafana/loki/v3/pkg/engine/internal/types" ) var tracer = otel.Tracer("pkg/engine/internal/executor") @@ -29,10 +32,10 @@ type Config struct { // GetExternalInputs is an optional function called for each node in the // plan. If GetExternalInputs returns a non-nil slice of Pipelines, they // will be used as inputs to the pipeline of node. - GetExternalInputs func(ctx context.Context, node physical.Node) []Pipeline + GetExternalInputs func(ctx context.Context, node physicalpb.Node) []Pipeline } -func Run(ctx context.Context, cfg Config, plan *physical.Plan, logger log.Logger) Pipeline { +func Run(ctx context.Context, cfg Config, plan *physicalpb.Plan, logger log.Logger) Pipeline { c := &Context{ plan: plan, batchSize: cfg.BatchSize, @@ -57,16 +60,16 @@ type Context struct { batchSize int64 logger log.Logger - plan *physical.Plan + plan *physicalpb.Plan evaluator expressionEvaluator bucket objstore.Bucket - getExternalInputs func(ctx context.Context, node physical.Node) []Pipeline + getExternalInputs func(ctx context.Context, node physicalpb.Node) []Pipeline mergePrefetchCount int } -func (c *Context) execute(ctx context.Context, node physical.Node) Pipeline { +func (c *Context) execute(ctx context.Context, node physicalpb.Node) Pipeline { children := c.plan.Children(node) inputs := make([]Pipeline, 0, len(children)) for _, child := range children { @@ -78,7 +81,7 @@ func (c *Context) execute(ctx context.Context, node physical.Node) Pipeline { } switch n := node.(type) { - case *physical.DataObjScan: + case *physicalpb.DataObjScan: // DataObjScan reads from object storage to determine the full pipeline to // construct, making it expensive to call during planning time. // @@ -86,39 +89,41 @@ func (c *Context) execute(ctx context.Context, node physical.Node) Pipeline { // which wraps the pipeline with a topk/limit without reintroducing // planning cost for thousands of scan nodes. return newLazyPipeline(func(ctx context.Context, _ []Pipeline) Pipeline { - return tracePipeline("physical.DataObjScan", c.executeDataObjScan(ctx, n)) + return tracePipeline("physicalpb.DataObjScan", c.executeDataObjScan(ctx, n)) }, inputs) - case *physical.TopK: - return tracePipeline("physical.TopK", c.executeTopK(ctx, n, inputs)) - case *physical.Limit: - return tracePipeline("physical.Limit", c.executeLimit(ctx, n, inputs)) - case *physical.Filter: - return tracePipeline("physical.Filter", c.executeFilter(ctx, n, inputs)) - case *physical.Projection: - return tracePipeline("physical.Projection", c.executeProjection(ctx, n, inputs)) - case *physical.RangeAggregation: - return tracePipeline("physical.RangeAggregation", c.executeRangeAggregation(ctx, n, inputs)) - case *physical.VectorAggregation: - return tracePipeline("physical.VectorAggregation", c.executeVectorAggregation(ctx, n, inputs)) - case *physical.ParseNode: - return tracePipeline("physical.ParseNode", c.executeParse(ctx, n, inputs)) - case *physical.ColumnCompat: - return tracePipeline("physical.ColumnCompat", c.executeColumnCompat(ctx, n, inputs)) - case *physical.Parallelize: - return tracePipeline("physical.Parallelize", c.executeParallelize(ctx, n, inputs)) - case *physical.ScanSet: - return tracePipeline("physical.ScanSet", c.executeScanSet(ctx, n)) + case *physicalpb.Limit: + return tracePipeline("physicalpb.Limit", c.executeLimit(ctx, n, inputs)) + case *physicalpb.Filter: + return tracePipeline("physicalpb.Filter", c.executeFilter(ctx, n, inputs)) + case *physicalpb.Projection: + return tracePipeline("physicalpb.Projection", c.executeProjection(ctx, n, inputs)) + case *physicalpb.AggregateRange: + return tracePipeline("physicalpb.RangeAggregation", c.executeRangeAggregation(ctx, n, inputs)) + case *physicalpb.AggregateVector: + return tracePipeline("physicalpb.VectorAggregation", c.executeVectorAggregation(ctx, n, inputs)) + case *physicalpb.Parse: + return tracePipeline("physicalpb.ParseNode", c.executeParse(ctx, n, inputs)) + case *physicalpb.ColumnCompat: + return tracePipeline("physicalpb.ColumnCompat", c.executeColumnCompat(ctx, n, inputs)) + case *physicalpb.Parallelize: + return tracePipeline("physicalpb.Parallelize", c.executeParallelize(ctx, n, inputs)) + case *physicalpb.ScanSet: + return tracePipeline("physicalpb.ScanSet", c.executeScanSet(ctx, n)) + case *physicalpb.TopK: + return tracePipeline("physicalpb.TopK", c.executeTopK(ctx, n, inputs)) default: return errorPipeline(ctx, fmt.Errorf("invalid node type: %T", node)) } } -func (c *Context) executeDataObjScan(ctx context.Context, node *physical.DataObjScan) Pipeline { +func (c *Context) executeDataObjScan(ctx context.Context, node *physicalpb.DataObjScan) Pipeline { ctx, span := tracer.Start(ctx, "Context.executeDataObjScan", trace.WithAttributes( - attribute.String("location", string(node.Location)), - attribute.Int("section", node.Section), - attribute.Int("num_stream_ids", len(node.StreamIDs)), + attribute.String("location", node.Location), + attribute.Int64("section", node.Section), + attribute.Stringer("direction", node.SortOrder), + attribute.Int("limit", int(node.Limit)), + attribute.Int("num_stream_ids", len(node.StreamIds)), attribute.Int("num_predicates", len(node.Predicates)), attribute.Int("num_projections", len(node.Projections)), )) @@ -128,7 +133,7 @@ func (c *Context) executeDataObjScan(ctx context.Context, node *physical.DataObj return errorPipeline(ctx, errors.New("no object store bucket configured")) } - obj, err := dataobj.FromBucket(ctx, c.bucket, string(node.Location)) + obj, err := dataobj.FromBucket(ctx, c.bucket, node.Location) if err != nil { return errorPipeline(ctx, fmt.Errorf("creating data object: %w", err)) } @@ -166,7 +171,7 @@ func (c *Context) executeDataObjScan(ctx context.Context, node *physical.DataObj } for i, sec := range obj.Sections().Filter(logs.CheckSection) { - if i != node.Section { + if int64(i) != node.Section { continue } @@ -185,7 +190,7 @@ func (c *Context) executeDataObjScan(ctx context.Context, node *physical.DataObj predicates := make([]logs.Predicate, 0, len(node.Predicates)) for _, p := range node.Predicates { - conv, err := buildLogsPredicate(p, logsSection.Columns()) + conv, err := buildLogsPredicate(*p, logsSection.Columns()) if err != nil { return errorPipeline(ctx, err) } @@ -204,30 +209,70 @@ func (c *Context) executeDataObjScan(ctx context.Context, node *physical.DataObj StreamsSection: streamsSection, LogsSection: logsSection, - StreamIDs: node.StreamIDs, + StreamIDs: node.StreamIds, Predicates: predicates, Projections: node.Projections, BatchSize: c.batchSize, - }, log.With(c.logger, "location", string(node.Location), "section", node.Section)) + }, log.With(c.logger, "location", node.Location, "section", node.Section)) + + sortType, sortDirection, err := logsSection.PrimarySortOrder() + if err != nil { + level.Warn(c.logger).Log("msg", "could not determine primary sort order for logs section, forcing topk sort", "err", err) + + sortType = logs.ColumnTypeInvalid + sortDirection = logs.SortDirectionUnspecified + } + + // Wrap our pipeline to enforce expected sorting. We always emit logs in + // timestamp-sorted order, so we need to sort if either the section doesn't + // match the expected sort order or the requested sort type is not timestamp. + // + // If it's already sorted, we wrap by LimitPipeline to enforce the limit + // given to the node (if defined). + if node.SortOrder != physicalpb.SORT_ORDER_INVALID && (node.SortOrder != logsSortOrder(sortDirection) || sortType != logs.ColumnTypeTimestamp) { + level.Debug(c.logger).Log("msg", "sorting logs section", "source_sort", sortType, "source_direction", sortDirection, "requested_sort", logs.ColumnTypeTimestamp, "requested_dir", node.SortOrder.String()) + + pipeline, err = newTopkPipeline(topkOptions{ + Inputs: []Pipeline{pipeline}, + + SortBy: []*physicalpb.ColumnExpression{ + { + Name: types.ColumnNameBuiltinTimestamp, + Type: physicalpb.COLUMN_TYPE_BUILTIN, + }, + }, + Ascending: node.SortOrder == physicalpb.SORT_ORDER_ASCENDING, + K: int64(node.Limit), + + MaxUnused: int(c.batchSize) * 2, + }) + if err != nil { + return errorPipeline(ctx, err) + } + span.AddEvent("injected topk") + } else if node.Limit > 0 { + pipeline = NewLimitPipeline(pipeline, 0, node.Limit) + span.AddEvent("injected limit") + } return pipeline } -func logsSortOrder(dir logs.SortDirection) physical.SortOrder { +func logsSortOrder(dir logs.SortDirection) physicalpb.SortOrder { switch dir { case logs.SortDirectionAscending: - return physical.ASC + return physicalpb.SORT_ORDER_ASCENDING case logs.SortDirectionDescending: - return physical.DESC + return physicalpb.SORT_ORDER_DESCENDING } - return physical.UNSORTED + return physicalpb.SORT_ORDER_INVALID } -func (c *Context) executeTopK(ctx context.Context, topK *physical.TopK, inputs []Pipeline) Pipeline { +func (c *Context) executeTopK(ctx context.Context, topK *physicalpb.TopK, inputs []Pipeline) Pipeline { ctx, span := tracer.Start(ctx, "Context.executeTopK", trace.WithAttributes( - attribute.Int("k", topK.K), + attribute.Int64("k", topK.K), attribute.Bool("ascending", topK.Ascending), )) defer span.End() @@ -242,7 +287,7 @@ func (c *Context) executeTopK(ctx context.Context, topK *physical.TopK, inputs [ pipeline, err := newTopkPipeline(topkOptions{ Inputs: inputs, - SortBy: []physical.ColumnExpression{topK.SortBy}, + SortBy: []*physicalpb.ColumnExpression{topK.SortBy}, Ascending: topK.Ascending, NullsFirst: topK.NullsFirst, K: topK.K, @@ -255,7 +300,7 @@ func (c *Context) executeTopK(ctx context.Context, topK *physical.TopK, inputs [ return pipeline } -func (c *Context) executeLimit(ctx context.Context, limit *physical.Limit, inputs []Pipeline) Pipeline { +func (c *Context) executeLimit(ctx context.Context, limit *physicalpb.Limit, inputs []Pipeline) Pipeline { ctx, span := tracer.Start(ctx, "Context.executeLimit", trace.WithAttributes( attribute.Int("skip", int(limit.Skip)), attribute.Int("fetch", int(limit.Fetch)), @@ -274,7 +319,7 @@ func (c *Context) executeLimit(ctx context.Context, limit *physical.Limit, input return NewLimitPipeline(inputs[0], limit.Skip, limit.Fetch) } -func (c *Context) executeFilter(ctx context.Context, filter *physical.Filter, inputs []Pipeline) Pipeline { +func (c *Context) executeFilter(ctx context.Context, filter *physicalpb.Filter, inputs []Pipeline) Pipeline { ctx, span := tracer.Start(ctx, "Context.executeFilter", trace.WithAttributes( attribute.Int("num_inputs", len(inputs)), )) @@ -291,7 +336,7 @@ func (c *Context) executeFilter(ctx context.Context, filter *physical.Filter, in return NewFilterPipeline(filter, inputs[0], c.evaluator) } -func (c *Context) executeProjection(ctx context.Context, proj *physical.Projection, inputs []Pipeline) Pipeline { +func (c *Context) executeProjection(ctx context.Context, proj *physicalpb.Projection, inputs []Pipeline) Pipeline { ctx, span := tracer.Start(ctx, "Context.executeProjection", trace.WithAttributes( attribute.Int("num_expressions", len(proj.Expressions)), attribute.Int("num_inputs", len(inputs)), @@ -318,13 +363,13 @@ func (c *Context) executeProjection(ctx context.Context, proj *physical.Projecti return p } -func (c *Context) executeRangeAggregation(ctx context.Context, plan *physical.RangeAggregation, inputs []Pipeline) Pipeline { +func (c *Context) executeRangeAggregation(ctx context.Context, plan *physicalpb.AggregateRange, inputs []Pipeline) Pipeline { ctx, span := tracer.Start(ctx, "Context.executeRangeAggregation", trace.WithAttributes( attribute.Int("num_partition_by", len(plan.PartitionBy)), - attribute.Int64("start_ts", plan.Start.UnixNano()), - attribute.Int64("end_ts", plan.End.UnixNano()), - attribute.Int64("range_interval", int64(plan.Range)), - attribute.Int64("step", int64(plan.Step)), + attribute.Int64("start_ts", plan.StartUnixNanos), + attribute.Int64("end_ts", plan.EndUnixNanos), + attribute.Int64("range_interval", plan.RangeNs), + attribute.Int64("step", plan.StepNs), attribute.Int("num_inputs", len(inputs)), )) defer span.End() @@ -335,10 +380,10 @@ func (c *Context) executeRangeAggregation(ctx context.Context, plan *physical.Ra pipeline, err := newRangeAggregationPipeline(inputs, c.evaluator, rangeAggregationOptions{ partitionBy: plan.PartitionBy, - startTs: plan.Start, - endTs: plan.End, - rangeInterval: plan.Range, - step: plan.Step, + startTs: time.Unix(0, plan.StartUnixNanos).UTC(), + endTs: time.Unix(0, plan.EndUnixNanos).UTC(), + rangeInterval: time.Duration(plan.RangeNs), + step: time.Duration(plan.StepNs), operation: plan.Operation, }) if err != nil { @@ -348,7 +393,7 @@ func (c *Context) executeRangeAggregation(ctx context.Context, plan *physical.Ra return pipeline } -func (c *Context) executeVectorAggregation(ctx context.Context, plan *physical.VectorAggregation, inputs []Pipeline) Pipeline { +func (c *Context) executeVectorAggregation(ctx context.Context, plan *physicalpb.AggregateVector, inputs []Pipeline) Pipeline { ctx, span := tracer.Start(ctx, "Context.executeVectorAggregation", trace.WithAttributes( attribute.Int("num_group_by", len(plan.GroupBy)), attribute.Int("num_inputs", len(inputs)), @@ -367,7 +412,7 @@ func (c *Context) executeVectorAggregation(ctx context.Context, plan *physical.V return pipeline } -func (c *Context) executeParse(ctx context.Context, parse *physical.ParseNode, inputs []Pipeline) Pipeline { +func (c *Context) executeParse(ctx context.Context, parse *physicalpb.Parse, inputs []Pipeline) Pipeline { if len(inputs) == 0 { return emptyPipeline() } @@ -379,7 +424,7 @@ func (c *Context) executeParse(ctx context.Context, parse *physical.ParseNode, i return NewParsePipeline(parse, inputs[0]) } -func (c *Context) executeColumnCompat(ctx context.Context, compat *physical.ColumnCompat, inputs []Pipeline) Pipeline { +func (c *Context) executeColumnCompat(ctx context.Context, compat *physicalpb.ColumnCompat, inputs []Pipeline) Pipeline { if len(inputs) == 0 { return emptyPipeline() } @@ -391,7 +436,7 @@ func (c *Context) executeColumnCompat(ctx context.Context, compat *physical.Colu return newColumnCompatibilityPipeline(compat, inputs[0]) } -func (c *Context) executeParallelize(ctx context.Context, _ *physical.Parallelize, inputs []Pipeline) Pipeline { +func (c *Context) executeParallelize(ctx context.Context, _ *physicalpb.Parallelize, inputs []Pipeline) Pipeline { if len(inputs) == 0 { return emptyPipeline() } else if len(inputs) > 1 { @@ -404,7 +449,7 @@ func (c *Context) executeParallelize(ctx context.Context, _ *physical.Paralleliz return inputs[0] } -func (c *Context) executeScanSet(ctx context.Context, set *physical.ScanSet) Pipeline { +func (c *Context) executeScanSet(ctx context.Context, set *physicalpb.ScanSet) Pipeline { // ScanSet typically gets partitioned by the scheduler into multiple scan // nodes. // @@ -416,7 +461,7 @@ func (c *Context) executeScanSet(ctx context.Context, set *physical.ScanSet) Pip for _, target := range set.Targets { switch target.Type { - case physical.ScanTypeDataObject: + case physicalpb.SCAN_TYPE_DATA_OBJECT: // Make sure projections and predicates get passed down to the // individual scan. partition := target.DataObject @@ -424,7 +469,7 @@ func (c *Context) executeScanSet(ctx context.Context, set *physical.ScanSet) Pip partition.Projections = set.Projections targets = append(targets, newLazyPipeline(func(ctx context.Context, _ []Pipeline) Pipeline { - return tracePipeline("physical.DataObjScan", c.executeDataObjScan(ctx, partition)) + return tracePipeline("physicalpb.DataObjScan", c.executeDataObjScan(ctx, partition)) }, nil)) default: return errorPipeline(ctx, fmt.Errorf("unrecognized ScanSet target %s", target.Type)) diff --git a/pkg/engine/internal/executor/executor_test.go b/pkg/engine/internal/executor/executor_test.go index e7f13dc79900b..091639e4ea1c2 100644 --- a/pkg/engine/internal/executor/executor_test.go +++ b/pkg/engine/internal/executor/executor_test.go @@ -6,7 +6,7 @@ import ( "github.com/go-kit/log" "github.com/stretchr/testify/require" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" ) func TestExecutor(t *testing.T) { @@ -19,7 +19,7 @@ func TestExecutor(t *testing.T) { t.Run("pipeline fails if plan has no root node", func(t *testing.T) { ctx := t.Context() - pipeline := Run(ctx, Config{}, &physical.Plan{}, log.NewNopLogger()) + pipeline := Run(ctx, Config{}, &physicalpb.Plan{}, log.NewNopLogger()) _, err := pipeline.Read(ctx) require.ErrorContains(t, err, "failed to execute pipeline: plan has no root node") }) @@ -29,7 +29,7 @@ func TestExecutor_Limit(t *testing.T) { t.Run("no inputs result in empty pipeline", func(t *testing.T) { ctx := t.Context() c := &Context{} - pipeline := c.executeLimit(ctx, &physical.Limit{}, nil) + pipeline := c.executeLimit(ctx, &physicalpb.Limit{}, nil) _, err := pipeline.Read(ctx) require.ErrorContains(t, err, EOF.Error()) }) @@ -37,7 +37,7 @@ func TestExecutor_Limit(t *testing.T) { t.Run("multiple inputs result in error", func(t *testing.T) { ctx := t.Context() c := &Context{} - pipeline := c.executeLimit(ctx, &physical.Limit{}, []Pipeline{emptyPipeline(), emptyPipeline()}) + pipeline := c.executeLimit(ctx, &physicalpb.Limit{}, []Pipeline{emptyPipeline(), emptyPipeline()}) _, err := pipeline.Read(ctx) require.ErrorContains(t, err, "limit expects exactly one input, got 2") }) @@ -47,7 +47,7 @@ func TestExecutor_Filter(t *testing.T) { t.Run("no inputs result in empty pipeline", func(t *testing.T) { ctx := t.Context() c := &Context{} - pipeline := c.executeFilter(ctx, &physical.Filter{}, nil) + pipeline := c.executeFilter(ctx, &physicalpb.Filter{}, nil) _, err := pipeline.Read(ctx) require.ErrorContains(t, err, EOF.Error()) }) @@ -55,7 +55,7 @@ func TestExecutor_Filter(t *testing.T) { t.Run("multiple inputs result in error", func(t *testing.T) { ctx := t.Context() c := &Context{} - pipeline := c.executeFilter(ctx, &physical.Filter{}, []Pipeline{emptyPipeline(), emptyPipeline()}) + pipeline := c.executeFilter(ctx, &physicalpb.Filter{}, []Pipeline{emptyPipeline(), emptyPipeline()}) _, err := pipeline.Read(ctx) require.ErrorContains(t, err, "filter expects exactly one input, got 2") }) @@ -65,16 +65,16 @@ func TestExecutor_Projection(t *testing.T) { t.Run("no inputs result in empty pipeline", func(t *testing.T) { ctx := t.Context() c := &Context{} - pipeline := c.executeProjection(ctx, &physical.Projection{}, nil) + pipeline := c.executeProjection(ctx, &physicalpb.Projection{}, nil) _, err := pipeline.Read(ctx) require.ErrorContains(t, err, EOF.Error()) }) t.Run("missing column expression results in error", func(t *testing.T) { ctx := t.Context() - cols := []physical.Expression{} + cols := []*physicalpb.Expression{} c := &Context{} - pipeline := c.executeProjection(ctx, &physical.Projection{Expressions: cols}, []Pipeline{emptyPipeline()}) + pipeline := c.executeProjection(ctx, &physicalpb.Projection{Expressions: cols}, []Pipeline{emptyPipeline()}) _, err := pipeline.Read(ctx) require.ErrorContains(t, err, "projection expects at least one expression, got 0") }) @@ -82,7 +82,7 @@ func TestExecutor_Projection(t *testing.T) { t.Run("multiple inputs result in error", func(t *testing.T) { ctx := t.Context() c := &Context{} - pipeline := c.executeProjection(ctx, &physical.Projection{}, []Pipeline{emptyPipeline(), emptyPipeline()}) + pipeline := c.executeProjection(ctx, &physicalpb.Projection{}, []Pipeline{emptyPipeline(), emptyPipeline()}) _, err := pipeline.Read(ctx) require.ErrorContains(t, err, "projection expects exactly one input, got 2") }) @@ -92,8 +92,8 @@ func TestExecutor_Parse(t *testing.T) { t.Run("no inputs result in empty pipeline", func(t *testing.T) { ctx := t.Context() c := &Context{} - pipeline := c.executeParse(ctx, &physical.ParseNode{ - Kind: physical.ParserLogfmt, + pipeline := c.executeParse(ctx, &physicalpb.Parse{ + Operation: physicalpb.PARSE_OP_LOGFMT, RequestedKeys: []string{"level", "status"}, }, nil) _, err := pipeline.Read(ctx) @@ -103,8 +103,8 @@ func TestExecutor_Parse(t *testing.T) { t.Run("multiple inputs result in error", func(t *testing.T) { ctx := t.Context() c := &Context{} - pipeline := c.executeParse(ctx, &physical.ParseNode{ - Kind: physical.ParserLogfmt, + pipeline := c.executeParse(ctx, &physicalpb.Parse{ + Operation: physicalpb.PARSE_OP_LOGFMT, RequestedKeys: []string{"level"}, }, []Pipeline{emptyPipeline(), emptyPipeline()}) _, err := pipeline.Read(ctx) diff --git a/pkg/engine/internal/executor/expressions.go b/pkg/engine/internal/executor/expressions.go index 4ab11b3d012e1..f7dba28c10046 100644 --- a/pkg/engine/internal/executor/expressions.go +++ b/pkg/engine/internal/executor/expressions.go @@ -5,7 +5,7 @@ import ( "github.com/apache/arrow-go/v18/arrow" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) @@ -16,18 +16,18 @@ func newExpressionEvaluator() expressionEvaluator { return expressionEvaluator{} } -func (e expressionEvaluator) eval(expr physical.Expression, input arrow.Record) (arrow.Array, error) { +func (e expressionEvaluator) eval(expr physicalpb.Expression, input arrow.Record) (arrow.Array, error) { - switch expr := expr.(type) { + switch expr := expr.Kind.(type) { - case *physical.LiteralExpr: - return NewScalar(expr.Literal, int(input.NumRows())), nil + case *physicalpb.Expression_LiteralExpression: + return NewScalar(*expr.LiteralExpression, int(input.NumRows())), nil - case *physical.ColumnExpr: - colIdent := semconv.NewIdentifier(expr.Ref.Column, expr.Ref.Type, types.Loki.String) + case *physicalpb.Expression_ColumnExpression: + colIdent := semconv.NewIdentifier(expr.ColumnExpression.Name, expr.ColumnExpression.Type, types.Loki.String) // For non-ambiguous columns, we can look up the column in the schema by its fully qualified name. - if expr.Ref.Type != types.ColumnTypeAmbiguous { + if expr.ColumnExpression.Type != physicalpb.COLUMN_TYPE_AMBIGUOUS { for idx, field := range input.Schema().Fields() { ident, err := semconv.ParseFQN(field.Name) if err != nil { @@ -40,7 +40,7 @@ func (e expressionEvaluator) eval(expr physical.Expression, input arrow.Record) } // For ambiguous columns, we need to filter on the name and type and combine matching columns into a CoalesceVector. - if expr.Ref.Type == types.ColumnTypeAmbiguous { + if expr.ColumnExpression.Type == physicalpb.COLUMN_TYPE_AMBIGUOUS { var fieldIndices []int var fieldIdents []*semconv.Identifier @@ -66,7 +66,7 @@ func (e expressionEvaluator) eval(expr physical.Expression, input arrow.Record) if ident.DataType() != types.Loki.String { return nil, fmt.Errorf("column %s has datatype %s, but expression expects %s", ident.ShortName(), ident.DataType(), types.Loki.String) } - vecs = append(vecs, &columnWithType{col: input.Column(idx), ct: ident.ColumnType()}) + vecs = append(vecs, &columnWithType{col: input.Column(idx), ct: ident.ColumnTypePhys()}) } // Single column matches @@ -82,27 +82,27 @@ func (e expressionEvaluator) eval(expr physical.Expression, input arrow.Record) // A non-existent column is represented as a string scalar with zero-value. // This reflects current behaviour, where a label filter `| foo=""` would match all if `foo` is not defined. - return NewScalar(types.NewLiteral(""), int(input.NumRows())), nil + return NewScalar(physicalpb.LiteralExpression{Kind: &physicalpb.LiteralExpression_StringLiteral{StringLiteral: &physicalpb.StringLiteral{Value: ""}}}, int(input.NumRows())), nil - case *physical.UnaryExpr: - lhr, err := e.eval(expr.Left, input) + case *physicalpb.Expression_UnaryExpression: + lhr, err := e.eval(*expr.UnaryExpression.Value, input) if err != nil { return nil, err } - fn, err := unaryFunctions.GetForSignature(expr.Op, lhr.DataType()) + fn, err := unaryFunctions.GetForSignature(expr.UnaryExpression.Op, lhr.DataType()) if err != nil { return nil, fmt.Errorf("failed to lookup unary function: %w", err) } return fn.Evaluate(lhr) - case *physical.BinaryExpr: - lhs, err := e.eval(expr.Left, input) + case *physicalpb.Expression_BinaryExpression: + lhs, err := e.eval(*expr.BinaryExpression.Left, input) if err != nil { return nil, err } - rhs, err := e.eval(expr.Right, input) + rhs, err := e.eval(*expr.BinaryExpression.Right, input) if err != nil { return nil, err } @@ -110,13 +110,13 @@ func (e expressionEvaluator) eval(expr physical.Expression, input arrow.Record) // At the moment we only support functions that accept the same input types. // TODO(chaudum): Compare Loki type, not Arrow type if lhs.DataType().ID() != rhs.DataType().ID() { - return nil, fmt.Errorf("failed to lookup binary function for signature %v(%v,%v): types do not match", expr.Op, lhs.DataType(), rhs.DataType()) + return nil, fmt.Errorf("failed to lookup binary function for signature %v(%v,%v): types do not match", expr.BinaryExpression.Op, lhs.DataType(), rhs.DataType()) } // TODO(chaudum): Resolve function by Loki type - fn, err := binaryFunctions.GetForSignature(expr.Op, lhs.DataType()) + fn, err := binaryFunctions.GetForSignature(expr.BinaryExpression.Op, lhs.DataType()) if err != nil { - return nil, fmt.Errorf("failed to lookup binary function for signature %v(%v,%v): %w", expr.Op, lhs.DataType(), rhs.DataType(), err) + return nil, fmt.Errorf("failed to lookup binary function for signature %v(%v,%v): %w", expr.BinaryExpression.Op, lhs.DataType(), rhs.DataType(), err) } return fn.Evaluate(lhs, rhs) } @@ -125,7 +125,7 @@ func (e expressionEvaluator) eval(expr physical.Expression, input arrow.Record) } // newFunc returns a new function that can evaluate an input against a binded expression. -func (e expressionEvaluator) newFunc(expr physical.Expression) evalFunc { +func (e expressionEvaluator) newFunc(expr physicalpb.Expression) evalFunc { return func(input arrow.Record) (arrow.Array, error) { return e.eval(expr, input) } @@ -135,5 +135,5 @@ type evalFunc func(input arrow.Record) (arrow.Array, error) type columnWithType struct { col arrow.Array - ct types.ColumnType + ct physicalpb.ColumnType } diff --git a/pkg/engine/internal/executor/expressions_test.go b/pkg/engine/internal/executor/expressions_test.go index 0aa084261afa9..f1f9aaa5ed40e 100644 --- a/pkg/engine/internal/executor/expressions_test.go +++ b/pkg/engine/internal/executor/expressions_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/util/arrowtest" @@ -91,7 +92,7 @@ func TestEvaluateLiteralExpression(t *testing.T) { n := len(words) rec := batch(n, time.Now()) - colVec, err := e.eval(literal, rec) + colVec, err := e.eval(*literal.ToExpression(), rec) require.NoError(t, err) require.Equalf(t, tt.arrowType, colVec.DataType().ID(), "expected: %v got: %v", tt.arrowType.String(), colVec.DataType().ID().String()) @@ -126,32 +127,28 @@ func TestEvaluateColumnExpression(t *testing.T) { e := newExpressionEvaluator() t.Run("unknown column", func(t *testing.T) { - colExpr := &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "does_not_exist", - Type: types.ColumnTypeBuiltin, - }, + colExpr := &physicalpb.ColumnExpression{ + Name: "does_not_exist", + Type: physicalpb.COLUMN_TYPE_BUILTIN, } n := len(words) rec := batch(n, time.Now()) - colVec, err := e.eval(colExpr, rec) + colVec, err := e.eval(*colExpr.ToExpression(), rec) require.NoError(t, err) require.Equal(t, arrow.STRING, colVec.DataType().ID()) }) t.Run("string(message)", func(t *testing.T) { - colExpr := &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "message", - Type: types.ColumnTypeBuiltin, - }, + colExpr := &physicalpb.ColumnExpression{ + Name: "message", + Type: physicalpb.COLUMN_TYPE_BUILTIN, } n := len(words) rec := batch(n, time.Now()) - colVec, err := e.eval(colExpr, rec) + colVec, err := e.eval(*colExpr.ToExpression(), rec) require.NoError(t, err) require.Equal(t, arrow.STRING, colVec.DataType().ID()) @@ -169,60 +166,60 @@ func TestEvaluateBinaryExpression(t *testing.T) { e := newExpressionEvaluator() t.Run("error if types do not match", func(t *testing.T) { - expr := &physical.BinaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{Column: "name", Type: types.ColumnTypeBuiltin}, - }, - Right: &physical.ColumnExpr{ - Ref: types.ColumnRef{Column: "timestamp", Type: types.ColumnTypeBuiltin}, - }, - Op: types.BinaryOpEq, + expr := &physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{ + Name: "name", Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), + Right: (&physicalpb.ColumnExpression{ + Name: "timestamp", Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), + Op: physicalpb.BINARY_OP_EQ, } - _, err := e.eval(expr, rec) - require.ErrorContains(t, err, "failed to lookup binary function for signature EQ(utf8,timestamp[ns, tz=UTC]): types do not match") + _, err := e.eval(*expr.ToExpression(), rec) + require.ErrorContains(t, err, "failed to lookup binary function for signature BINARY_OP_EQ(utf8,timestamp[ns, tz=UTC]): types do not match") }) t.Run("error if function for signature is not registered", func(t *testing.T) { - expr := &physical.BinaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{Column: "name", Type: types.ColumnTypeBuiltin}, - }, - Right: &physical.ColumnExpr{ - Ref: types.ColumnRef{Column: "name", Type: types.ColumnTypeBuiltin}, - }, - Op: types.BinaryOpXor, + expr := &physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{ + Name: "name", Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), + Right: (&physicalpb.ColumnExpression{ + Name: "name", Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), + Op: physicalpb.BINARY_OP_XOR, } - _, err := e.eval(expr, rec) - require.ErrorContains(t, err, "failed to lookup binary function for signature XOR(utf8,utf8): not implemented") + _, err := e.eval(*expr.ToExpression(), rec) + require.ErrorContains(t, err, "failed to lookup binary function for signature BINARY_OP_XOR(utf8,utf8): not implemented") }) t.Run("EQ(string,string)", func(t *testing.T) { - expr := &physical.BinaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{Column: "name", Type: types.ColumnTypeBuiltin}, - }, - Right: physical.NewLiteral("Charlie"), - Op: types.BinaryOpEq, + expr := &physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{ + Name: "name", Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), + Right: physical.NewLiteral("Charlie").ToExpression(), + Op: physicalpb.BINARY_OP_EQ, } - res, err := e.eval(expr, rec) + res, err := e.eval(*expr.ToExpression(), rec) require.NoError(t, err) result := collectBooleanArray(res.(*array.Boolean)) require.Equal(t, []bool{false, false, true, false, false, false, false, false, false, false}, result) }) t.Run("GT(float,float)", func(t *testing.T) { - expr := &physical.BinaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{Column: "value", Type: types.ColumnTypeBuiltin}, - }, - Right: physical.NewLiteral(0.5), - Op: types.BinaryOpGt, + expr := &physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{ + Name: "value", Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), + Right: physical.NewLiteral(0.5).ToExpression(), + Op: physicalpb.BINARY_OP_GT, } - res, err := e.eval(expr, rec) + res, err := e.eval(*expr.ToExpression(), rec) require.NoError(t, err) result := collectBooleanArray(res.(*array.Boolean)) require.Equal(t, []bool{false, true, false, true, false, true, true, false, true, false}, result) @@ -301,14 +298,12 @@ null,null,null` e := newExpressionEvaluator() t.Run("ambiguous column should use per-row precedence order", func(t *testing.T) { - colExpr := &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "test", - Type: types.ColumnTypeAmbiguous, - }, + colExpr := &physicalpb.ColumnExpression{ + Name: "test", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, } - colVec, err := e.eval(colExpr, record) + colVec, err := e.eval(*colExpr.ToExpression(), record) require.NoError(t, err) require.Equal(t, arrow.STRING, colVec.DataType().ID()) @@ -333,14 +328,12 @@ label_2 singleRecord, err := CSVToArrow(fields, data) require.NoError(t, err) - colExpr := &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "single", - Type: types.ColumnTypeAmbiguous, - }, + colExpr := &physicalpb.ColumnExpression{ + Name: "single", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, } - colVec, err := e.eval(colExpr, singleRecord) + colVec, err := e.eval(*colExpr.ToExpression(), singleRecord) require.NoError(t, err) require.Equal(t, arrow.STRING, colVec.DataType().ID()) @@ -352,14 +345,12 @@ label_2 }) t.Run("ambiguous column with no matching columns should return default scalar", func(t *testing.T) { - colExpr := &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "nonexistent", - Type: types.ColumnTypeAmbiguous, - }, + colExpr := &physicalpb.ColumnExpression{ + Name: "nonexistent", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, } - colVec, err := e.eval(colExpr, record) + colVec, err := e.eval(*colExpr.ToExpression(), record) require.NoError(t, err) require.Equal(t, arrow.STRING, colVec.DataType().ID()) }) @@ -367,25 +358,23 @@ label_2 func TestEvaluateUnaryCastExpression(t *testing.T) { colMsg := semconv.ColumnIdentMessage - colStatusCode := semconv.NewIdentifier("status_code", types.ColumnTypeMetadata, types.Loki.String) - colTimeout := semconv.NewIdentifier("timeout", types.ColumnTypeParsed, types.Loki.String) - colMixedValues := semconv.NewIdentifier("mixed_values", types.ColumnTypeMetadata, types.Loki.String) + colStatusCode := semconv.NewIdentifier("status_code", physicalpb.COLUMN_TYPE_METADATA, types.Loki.String) + colTimeout := semconv.NewIdentifier("timeout", physicalpb.COLUMN_TYPE_PARSED, types.Loki.String) + colMixedValues := semconv.NewIdentifier("mixed_values", physicalpb.COLUMN_TYPE_METADATA, types.Loki.String) t.Run("unknown column", func(t *testing.T) { e := newExpressionEvaluator() - expr := &physical.UnaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "does_not_exist", - Type: types.ColumnTypeAmbiguous, - }, - }, - Op: types.UnaryOpCastFloat, - } + expr := (&physicalpb.UnaryExpression{ + Value: (&physicalpb.ColumnExpression{ + Name: "does_not_exist", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, + }).ToExpression(), + Op: physicalpb.UNARY_OP_CAST_FLOAT, + }).ToExpression() n := len(words) rec := batch(n, time.Now()) - colVec, err := e.eval(expr, rec) + colVec, err := e.eval(*expr, rec) require.NoError(t, err) id := colVec.DataType().ID() @@ -413,15 +402,13 @@ func TestEvaluateUnaryCastExpression(t *testing.T) { }) t.Run("cast column generates a value", func(t *testing.T) { - expr := &physical.UnaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "status_code", - Type: types.ColumnTypeAmbiguous, - }, - }, - Op: types.UnaryOpCastBytes, - } + expr := (&physicalpb.UnaryExpression{ + Value: (&physicalpb.ColumnExpression{ + Name: "status_code", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, + }).ToExpression(), + Op: physicalpb.UNARY_OP_CAST_BYTES, + }).ToExpression() e := newExpressionEvaluator() @@ -441,7 +428,7 @@ func TestEvaluateUnaryCastExpression(t *testing.T) { record := rows.Record(memory.DefaultAllocator, schema) - colVec, err := e.eval(expr, record) + colVec, err := e.eval(*expr, record) require.NoError(t, err) id := colVec.DataType().ID() require.Equal(t, arrow.STRUCT, id) @@ -460,15 +447,13 @@ func TestEvaluateUnaryCastExpression(t *testing.T) { }) t.Run("cast column generates a value from a parsed column", func(t *testing.T) { - expr := &physical.UnaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "timeout", - Type: types.ColumnTypeAmbiguous, - }, - }, - Op: types.UnaryOpCastDuration, - } + expr := (&physicalpb.UnaryExpression{ + Value: (&physicalpb.ColumnExpression{ + Name: "timeout", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, + }).ToExpression(), + Op: physicalpb.UNARY_OP_CAST_DURATION, + }).ToExpression() e := newExpressionEvaluator() @@ -488,7 +473,7 @@ func TestEvaluateUnaryCastExpression(t *testing.T) { record := rows.Record(memory.DefaultAllocator, schema) - colVec, err := e.eval(expr, record) + colVec, err := e.eval(*expr, record) require.NoError(t, err) id := colVec.DataType().ID() require.Equal(t, arrow.STRUCT, id) @@ -506,15 +491,13 @@ func TestEvaluateUnaryCastExpression(t *testing.T) { }) t.Run("cast operation tracks errors", func(t *testing.T) { - colExpr := &physical.UnaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "mixed_values", - Type: types.ColumnTypeAmbiguous, - }, - }, - Op: types.UnaryOpCastFloat, - } + expr := (&physicalpb.UnaryExpression{ + Value: (&physicalpb.ColumnExpression{ + Name: "mixed_values", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, + }).ToExpression(), + Op: physicalpb.UNARY_OP_CAST_FLOAT, + }).ToExpression() e := newExpressionEvaluator() @@ -535,7 +518,7 @@ func TestEvaluateUnaryCastExpression(t *testing.T) { record := rows.Record(memory.DefaultAllocator, schema) - colVec, err := e.eval(colExpr, record) + colVec, err := e.eval(*expr, record) require.NoError(t, err) id := colVec.DataType().ID() require.Equal(t, arrow.STRUCT, id) diff --git a/pkg/engine/internal/executor/filter.go b/pkg/engine/internal/executor/filter.go index 82530653ac56b..399bd580e1a41 100644 --- a/pkg/engine/internal/executor/filter.go +++ b/pkg/engine/internal/executor/filter.go @@ -8,10 +8,10 @@ import ( "github.com/apache/arrow-go/v18/arrow/array" "github.com/apache/arrow-go/v18/arrow/memory" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" ) -func NewFilterPipeline(filter *physical.Filter, input Pipeline, evaluator expressionEvaluator) *GenericPipeline { +func NewFilterPipeline(filter *physicalpb.Filter, input Pipeline, evaluator expressionEvaluator) *GenericPipeline { return newGenericPipeline(func(ctx context.Context, inputs []Pipeline) (arrow.Record, error) { // Pull the next item from the input pipeline input := inputs[0] @@ -23,7 +23,7 @@ func NewFilterPipeline(filter *physical.Filter, input Pipeline, evaluator expres cols := make([]*array.Boolean, 0, len(filter.Predicates)) for i, pred := range filter.Predicates { - vec, err := evaluator.eval(pred, batch) + vec, err := evaluator.eval(*pred, batch) if err != nil { return nil, err } diff --git a/pkg/engine/internal/executor/filter_test.go b/pkg/engine/internal/executor/filter_test.go index edd74e3c053ad..7086d1ee133bf 100644 --- a/pkg/engine/internal/executor/filter_test.go +++ b/pkg/engine/internal/executor/filter_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" - "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/util/arrowtest" ) @@ -38,8 +38,8 @@ func TestNewFilterPipeline(t *testing.T) { truePredicate := physical.NewLiteral(true) // Create a Filter node - filter := &physical.Filter{ - Predicates: []physical.Expression{truePredicate}, + filter := &physicalpb.Filter{ + Predicates: []*physicalpb.Expression{truePredicate.ToExpression()}, } // Create filter pipeline @@ -76,8 +76,8 @@ func TestNewFilterPipeline(t *testing.T) { falsePredicate := physical.NewLiteral(false) // Create a Filter node - filter := &physical.Filter{ - Predicates: []physical.Expression{falsePredicate}, + filter := &physicalpb.Filter{ + Predicates: []*physicalpb.Expression{falsePredicate.ToExpression()}, } // Create filter pipeline @@ -107,13 +107,13 @@ func TestNewFilterPipeline(t *testing.T) { defer input.Close() // Create a filter predicate that uses the 'valid' column directly - validColumnPredicate := &physical.ColumnExpr{ - Ref: createColumnRef("valid"), + validColumnPredicate := &physicalpb.ColumnExpression{ + Name: "valid", Type: physicalpb.COLUMN_TYPE_BUILTIN, } // Create a Filter node - filter := &physical.Filter{ - Predicates: []physical.Expression{validColumnPredicate}, + filter := &physicalpb.Filter{ + Predicates: []*physicalpb.Expression{validColumnPredicate.ToExpression()}, } // Create filter pipeline @@ -153,18 +153,18 @@ func TestNewFilterPipeline(t *testing.T) { defer input.Close() // Create a Filter node - filter := &physical.Filter{ - Predicates: []physical.Expression{ - &physical.BinaryExpr{ - Left: &physical.ColumnExpr{Ref: createColumnRef("name")}, - Right: physical.NewLiteral("Bob"), - Op: types.BinaryOpEq, - }, - &physical.BinaryExpr{ - Left: &physical.ColumnExpr{Ref: createColumnRef("valid")}, - Right: physical.NewLiteral(false), - Op: types.BinaryOpNeq, - }, + filter := &physicalpb.Filter{ + Predicates: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{Name: "name", Type: physicalpb.COLUMN_TYPE_BUILTIN}).ToExpression(), + Right: physical.NewLiteral("Bob").ToExpression(), + Op: physicalpb.BINARY_OP_EQ, + }).ToExpression(), + (&physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{Name: "valid", Type: physicalpb.COLUMN_TYPE_BUILTIN}).ToExpression(), + Right: physical.NewLiteral(false).ToExpression(), + Op: physicalpb.BINARY_OP_NEQ, + }).ToExpression(), }, } @@ -203,8 +203,8 @@ func TestNewFilterPipeline(t *testing.T) { truePredicate := physical.NewLiteral(true) // Create a Filter node - filter := &physical.Filter{ - Predicates: []physical.Expression{truePredicate}, + filter := &physicalpb.Filter{ + Predicates: []*physicalpb.Expression{truePredicate.ToExpression()}, } // Create filter pipeline @@ -238,13 +238,13 @@ func TestNewFilterPipeline(t *testing.T) { defer input.Close() // Create a filter predicate that uses the 'valid' column directly - validColumnPredicate := &physical.ColumnExpr{ - Ref: createColumnRef("valid"), + validColumnPredicate := &physicalpb.ColumnExpression{ + Name: "valid", Type: physicalpb.COLUMN_TYPE_BUILTIN, } // Create a Filter node - filter := &physical.Filter{ - Predicates: []physical.Expression{validColumnPredicate}, + filter := &physicalpb.Filter{ + Predicates: []*physicalpb.Expression{validColumnPredicate.ToExpression()}, } // Create filter pipeline @@ -294,13 +294,13 @@ func TestNewFilterPipeline(t *testing.T) { defer input.Close() // Create a filter predicate that uses the 'valid' column directly - validColumnPredicate := &physical.ColumnExpr{ - Ref: createColumnRef("valid"), + validColumnPredicate := &physicalpb.ColumnExpression{ + Name: "valid", Type: physicalpb.COLUMN_TYPE_BUILTIN, } // Create a Filter node - filter := &physical.Filter{ - Predicates: []physical.Expression{validColumnPredicate}, + filter := &physicalpb.Filter{ + Predicates: []*physicalpb.Expression{validColumnPredicate.ToExpression()}, } // Create filter pipeline diff --git a/pkg/engine/internal/executor/functions.go b/pkg/engine/internal/executor/functions.go index 9e3bb55bbff08..d81d88600ad0d 100644 --- a/pkg/engine/internal/executor/functions.go +++ b/pkg/engine/internal/executor/functions.go @@ -11,7 +11,7 @@ import ( "github.com/apache/arrow-go/v18/arrow/memory" "github.com/grafana/loki/v3/pkg/engine/internal/errors" - "github.com/grafana/loki/v3/pkg/engine/internal/types" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" ) var ( @@ -20,79 +20,79 @@ var ( ) func init() { - // Functions for [types.BinaryOpDiv] - binaryFunctions.register(types.BinaryOpDiv, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return a / b, nil }}) - binaryFunctions.register(types.BinaryOpDiv, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return float64(a) / float64(b), nil }}) - // Functions for [types.BinaryOpAdd] - binaryFunctions.register(types.BinaryOpAdd, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return a + b, nil }}) - binaryFunctions.register(types.BinaryOpAdd, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return float64(a) + float64(b), nil }}) - // Functions for [types.BinaryOpSub] - binaryFunctions.register(types.BinaryOpSub, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return a - b, nil }}) - binaryFunctions.register(types.BinaryOpSub, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return float64(a) - float64(b), nil }}) - // Functions for [types.BinaryOpMul] - binaryFunctions.register(types.BinaryOpMul, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return a * b, nil }}) - binaryFunctions.register(types.BinaryOpMul, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return float64(a) * float64(b), nil }}) - // Functions for [types.BinaryOpMod] - binaryFunctions.register(types.BinaryOpMod, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return math.Mod(a, b), nil }}) - binaryFunctions.register(types.BinaryOpMod, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return float64(a % b), nil }}) - // Functions for [types.BinaryOpPow] - binaryFunctions.register(types.BinaryOpPow, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return math.Pow(a, b), nil }}) - binaryFunctions.register(types.BinaryOpPow, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return math.Pow(float64(a), float64(b)), nil }}) - - // Functions for [types.BinaryOpEq] - binaryFunctions.register(types.BinaryOpEq, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return a == b, nil }}) - binaryFunctions.register(types.BinaryOpEq, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a == b, nil }}) - binaryFunctions.register(types.BinaryOpEq, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a == b, nil }}) - binaryFunctions.register(types.BinaryOpEq, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a == b, nil }}) - binaryFunctions.register(types.BinaryOpEq, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a == b, nil }}) - // Functions for [types.BinaryOpNeq] - binaryFunctions.register(types.BinaryOpNeq, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return a != b, nil }}) - binaryFunctions.register(types.BinaryOpNeq, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a != b, nil }}) - binaryFunctions.register(types.BinaryOpNeq, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a != b, nil }}) - binaryFunctions.register(types.BinaryOpNeq, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a != b, nil }}) - binaryFunctions.register(types.BinaryOpNeq, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a != b, nil }}) - // Functions for [types.BinaryOpGt] - binaryFunctions.register(types.BinaryOpGt, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return boolToInt(a) > boolToInt(b), nil }}) - binaryFunctions.register(types.BinaryOpGt, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a > b, nil }}) - binaryFunctions.register(types.BinaryOpGt, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a > b, nil }}) - binaryFunctions.register(types.BinaryOpGt, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a > b, nil }}) - binaryFunctions.register(types.BinaryOpGt, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a > b, nil }}) - // Functions for [types.BinaryOpGte] - binaryFunctions.register(types.BinaryOpGte, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return boolToInt(a) >= boolToInt(b), nil }}) - binaryFunctions.register(types.BinaryOpGte, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a >= b, nil }}) - binaryFunctions.register(types.BinaryOpGte, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a >= b, nil }}) - binaryFunctions.register(types.BinaryOpGte, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a >= b, nil }}) - binaryFunctions.register(types.BinaryOpGte, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a >= b, nil }}) - // Functions for [types.BinaryOpLt] - binaryFunctions.register(types.BinaryOpLt, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return boolToInt(a) < boolToInt(b), nil }}) - binaryFunctions.register(types.BinaryOpLt, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a < b, nil }}) - binaryFunctions.register(types.BinaryOpLt, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a < b, nil }}) - binaryFunctions.register(types.BinaryOpLt, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a < b, nil }}) - binaryFunctions.register(types.BinaryOpLt, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a < b, nil }}) - // Functions for [types.BinaryOpLte] - binaryFunctions.register(types.BinaryOpLte, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return boolToInt(a) <= boolToInt(b), nil }}) - binaryFunctions.register(types.BinaryOpLte, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a <= b, nil }}) - binaryFunctions.register(types.BinaryOpLte, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a <= b, nil }}) - binaryFunctions.register(types.BinaryOpLte, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a <= b, nil }}) - binaryFunctions.register(types.BinaryOpLte, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a <= b, nil }}) - // Functions for [types.BinaryOpMatchSubstr] - binaryFunctions.register(types.BinaryOpMatchSubstr, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return strings.Contains(a, b), nil }}) - // Functions for [types.BinaryOpNotMatchSubstr] - binaryFunctions.register(types.BinaryOpNotMatchSubstr, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return !strings.Contains(a, b), nil }}) - // Functions for [types.BinaryOpMatchRe] + // Functions for [physicalpb.BINARY_OP_DIV] + binaryFunctions.register(physicalpb.BINARY_OP_DIV, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return a / b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_DIV, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return float64(a) / float64(b), nil }}) + // Functions for [physicalpb.BINARY_OP_ADD] + binaryFunctions.register(physicalpb.BINARY_OP_ADD, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return a + b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_ADD, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return float64(a) + float64(b), nil }}) + // Functions for [physicalpb.BINARY_OP_SUB] + binaryFunctions.register(physicalpb.BINARY_OP_SUB, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return a - b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_SUB, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return float64(a) - float64(b), nil }}) + // Functions for [physicalpb.BINARY_OP_MUL] + binaryFunctions.register(physicalpb.BINARY_OP_MUL, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return a * b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_MUL, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return float64(a) * float64(b), nil }}) + // Functions for [physicalpb.BINARY_OP_MOD] + binaryFunctions.register(physicalpb.BINARY_OP_MOD, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return math.Mod(a, b), nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_MOD, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return float64(a % b), nil }}) + // Functions for [physicalpb.BINARY_OP_POW] + binaryFunctions.register(physicalpb.BINARY_OP_POW, arrow.PrimitiveTypes.Float64, &genericFloat64Function[*array.Float64, float64]{eval: func(a, b float64) (float64, error) { return math.Pow(a, b), nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_POW, arrow.PrimitiveTypes.Int64, &genericFloat64Function[*array.Int64, int64]{eval: func(a, b int64) (float64, error) { return math.Pow(float64(a), float64(b)), nil }}) + + // Functions for [physicalpb.BINARY_OP_EQ] + binaryFunctions.register(physicalpb.BINARY_OP_EQ, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return a == b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_EQ, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a == b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_EQ, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a == b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_EQ, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a == b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_EQ, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a == b, nil }}) + // Functions for [physicalpb.BINARY_OP_NEQ] + binaryFunctions.register(physicalpb.BINARY_OP_NEQ, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return a != b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_NEQ, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a != b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_NEQ, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a != b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_NEQ, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a != b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_NEQ, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a != b, nil }}) + // Functions for [physicalpb.BINARY_OP_GT] + binaryFunctions.register(physicalpb.BINARY_OP_GT, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return boolToInt(a) > boolToInt(b), nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_GT, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a > b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_GT, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a > b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_GT, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a > b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_GT, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a > b, nil }}) + // Functions for [physicalpb.BINARY_OP_GTE] + binaryFunctions.register(physicalpb.BINARY_OP_GTE, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return boolToInt(a) >= boolToInt(b), nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_GTE, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a >= b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_GTE, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a >= b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_GTE, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a >= b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_GTE, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a >= b, nil }}) + // Functions for [physicalpb.BINARY_OP_LT] + binaryFunctions.register(physicalpb.BINARY_OP_LT, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return boolToInt(a) < boolToInt(b), nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_LT, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a < b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_LT, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a < b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_LT, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a < b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_LT, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a < b, nil }}) + // Functions for [physicalpb.BINARY_OP_LTE] + binaryFunctions.register(physicalpb.BINARY_OP_LTE, arrow.FixedWidthTypes.Boolean, &genericBoolFunction[*array.Boolean, bool]{eval: func(a, b bool) (bool, error) { return boolToInt(a) <= boolToInt(b), nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_LTE, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return a <= b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_LTE, arrow.PrimitiveTypes.Int64, &genericBoolFunction[*array.Int64, int64]{eval: func(a, b int64) (bool, error) { return a <= b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_LTE, arrow.FixedWidthTypes.Timestamp_ns, &genericBoolFunction[*array.Timestamp, arrow.Timestamp]{eval: func(a, b arrow.Timestamp) (bool, error) { return a <= b, nil }}) + binaryFunctions.register(physicalpb.BINARY_OP_LTE, arrow.PrimitiveTypes.Float64, &genericBoolFunction[*array.Float64, float64]{eval: func(a, b float64) (bool, error) { return a <= b, nil }}) + // Functions for [physicalpb.BINARY_OP_MATCH_SUBSTR] + binaryFunctions.register(physicalpb.BINARY_OP_MATCH_SUBSTR, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return strings.Contains(a, b), nil }}) + // Functions for [physicalpb.BINARY_OP_NOT_MATCH_SUBSTR] + binaryFunctions.register(physicalpb.BINARY_OP_NOT_MATCH_SUBSTR, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { return !strings.Contains(a, b), nil }}) + // Functions for [physicalpb.BINARY_OP_MATCH_RE] // TODO(chaudum): Performance of regex evaluation can be improved if RHS is a Scalar, // because the regexp would only need to compiled once for the given scalar value. // TODO(chaudum): Performance of regex evaluation can be improved by simplifying the regex, // see pkg/logql/log/filter.go:645 - binaryFunctions.register(types.BinaryOpMatchRe, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { + binaryFunctions.register(physicalpb.BINARY_OP_MATCH_RE, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { reg, err := regexp.Compile(b) if err != nil { return false, err } return reg.Match([]byte(a)), nil }}) - // Functions for [types.BinaryOpNotMatchRe] - binaryFunctions.register(types.BinaryOpNotMatchRe, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { + // Functions for [physicalpb.BINARY_OP_NOT_MATCH_RE] + binaryFunctions.register(physicalpb.BINARY_OP_NOT_MATCH_RE, arrow.BinaryTypes.String, &genericBoolFunction[*array.String, string]{eval: func(a, b string) (bool, error) { reg, err := regexp.Compile(b) if err != nil { return false, err @@ -101,14 +101,14 @@ func init() { }}) // Cast functions - unaryFunctions.register(types.UnaryOpCastFloat, arrow.BinaryTypes.String, castFn(types.UnaryOpCastFloat)) - unaryFunctions.register(types.UnaryOpCastBytes, arrow.BinaryTypes.String, castFn(types.UnaryOpCastBytes)) - unaryFunctions.register(types.UnaryOpCastDuration, arrow.BinaryTypes.String, castFn(types.UnaryOpCastDuration)) + unaryFunctions.register(physicalpb.UNARY_OP_CAST_FLOAT, arrow.BinaryTypes.String, castFn(physicalpb.UNARY_OP_CAST_FLOAT)) + unaryFunctions.register(physicalpb.UNARY_OP_CAST_BYTES, arrow.BinaryTypes.String, castFn(physicalpb.UNARY_OP_CAST_BYTES)) + unaryFunctions.register(physicalpb.UNARY_OP_CAST_DURATION, arrow.BinaryTypes.String, castFn(physicalpb.UNARY_OP_CAST_DURATION)) } type UnaryFunctionRegistry interface { - register(types.UnaryOp, arrow.DataType, UnaryFunction) - GetForSignature(types.UnaryOp, arrow.DataType) (UnaryFunction, error) + register(physicalpb.UnaryOp, arrow.DataType, UnaryFunction) + GetForSignature(physicalpb.UnaryOp, arrow.DataType) (UnaryFunction, error) } type UnaryFunction interface { @@ -122,13 +122,13 @@ func (f UnaryFunc) Evaluate(lhs arrow.Array) (arrow.Array, error) { } type unaryFuncReg struct { - reg map[types.UnaryOp]map[arrow.DataType]UnaryFunction + reg map[physicalpb.UnaryOp]map[arrow.DataType]UnaryFunction } // register implements UnaryFunctionRegistry. -func (u *unaryFuncReg) register(op types.UnaryOp, ltype arrow.DataType, f UnaryFunction) { +func (u *unaryFuncReg) register(op physicalpb.UnaryOp, ltype arrow.DataType, f UnaryFunction) { if u.reg == nil { - u.reg = make(map[types.UnaryOp]map[arrow.DataType]UnaryFunction) + u.reg = make(map[physicalpb.UnaryOp]map[arrow.DataType]UnaryFunction) } if _, ok := u.reg[op]; !ok { u.reg[op] = make(map[arrow.DataType]UnaryFunction) @@ -138,7 +138,7 @@ func (u *unaryFuncReg) register(op types.UnaryOp, ltype arrow.DataType, f UnaryF } // GetForSignature implements UnaryFunctionRegistry. -func (u *unaryFuncReg) GetForSignature(op types.UnaryOp, ltype arrow.DataType) (UnaryFunction, error) { +func (u *unaryFuncReg) GetForSignature(op physicalpb.UnaryOp, ltype arrow.DataType) (UnaryFunction, error) { // Get registered functions for the specific operation reg, ok := u.reg[op] if !ok { @@ -153,8 +153,8 @@ func (u *unaryFuncReg) GetForSignature(op types.UnaryOp, ltype arrow.DataType) ( } type BinaryFunctionRegistry interface { - register(types.BinaryOp, arrow.DataType, BinaryFunction) - GetForSignature(types.BinaryOp, arrow.DataType) (BinaryFunction, error) + register(physicalpb.BinaryOp, arrow.DataType, BinaryFunction) + GetForSignature(physicalpb.BinaryOp, arrow.DataType) (BinaryFunction, error) } type BinaryFunction interface { @@ -162,13 +162,13 @@ type BinaryFunction interface { } type binaryFuncReg struct { - reg map[types.BinaryOp]map[arrow.DataType]BinaryFunction + reg map[physicalpb.BinaryOp]map[arrow.DataType]BinaryFunction } // register implements BinaryFunctionRegistry. -func (b *binaryFuncReg) register(op types.BinaryOp, ty arrow.DataType, f BinaryFunction) { +func (b *binaryFuncReg) register(op physicalpb.BinaryOp, ty arrow.DataType, f BinaryFunction) { if b.reg == nil { - b.reg = make(map[types.BinaryOp]map[arrow.DataType]BinaryFunction) + b.reg = make(map[physicalpb.BinaryOp]map[arrow.DataType]BinaryFunction) } if _, ok := b.reg[op]; !ok { b.reg[op] = make(map[arrow.DataType]BinaryFunction) @@ -178,7 +178,7 @@ func (b *binaryFuncReg) register(op types.BinaryOp, ty arrow.DataType, f BinaryF } // GetForSignature implements BinaryFunctionRegistry. -func (b *binaryFuncReg) GetForSignature(op types.BinaryOp, ltype arrow.DataType) (BinaryFunction, error) { +func (b *binaryFuncReg) GetForSignature(op physicalpb.BinaryOp, ltype arrow.DataType) (BinaryFunction, error) { // Get registered functions for the specific operation reg, ok := b.reg[op] if !ok { diff --git a/pkg/engine/internal/executor/functions_test.go b/pkg/engine/internal/executor/functions_test.go index f7e11d6d1cef1..c8c5bb8f45145 100644 --- a/pkg/engine/internal/executor/functions_test.go +++ b/pkg/engine/internal/executor/functions_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/grafana/loki/v3/pkg/engine/internal/types" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" ) // Helper function to create a boolean array @@ -105,85 +105,85 @@ func extractBoolValues(result arrow.Array) []bool { func TestBinaryFunctionRegistry_GetForSignature(t *testing.T) { tests := []struct { name string - op types.BinaryOp + op physicalpb.BinaryOp dataType arrow.DataType expectError bool }{ { name: "valid equality operation for boolean", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, dataType: arrow.FixedWidthTypes.Boolean, expectError: false, }, { name: "valid equality operation for string", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, dataType: arrow.BinaryTypes.String, expectError: false, }, { name: "valid equality operation for int64", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, dataType: arrow.PrimitiveTypes.Int64, expectError: false, }, { name: "valid equality operation for timestamp", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, dataType: arrow.FixedWidthTypes.Timestamp_ns, expectError: false, }, { name: "valid equality operation for float64", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, dataType: arrow.PrimitiveTypes.Float64, expectError: false, }, { name: "valid string contains operation", - op: types.BinaryOpMatchSubstr, + op: physicalpb.BINARY_OP_MATCH_SUBSTR, dataType: arrow.BinaryTypes.String, expectError: false, }, { name: "valid regex match operation", - op: types.BinaryOpMatchRe, + op: physicalpb.BINARY_OP_MATCH_RE, dataType: arrow.BinaryTypes.String, expectError: false, }, { name: "valid div operation", - op: types.BinaryOpDiv, + op: physicalpb.BINARY_OP_DIV, dataType: arrow.PrimitiveTypes.Float64, expectError: false, }, { name: "valid add operation", - op: types.BinaryOpAdd, + op: physicalpb.BINARY_OP_ADD, dataType: arrow.PrimitiveTypes.Float64, expectError: false, }, { name: "valid Mul operation", - op: types.BinaryOpMul, + op: physicalpb.BINARY_OP_MUL, dataType: arrow.PrimitiveTypes.Float64, expectError: false, }, { name: "valid sub operation", - op: types.BinaryOpSub, + op: physicalpb.BINARY_OP_SUB, dataType: arrow.PrimitiveTypes.Float64, expectError: false, }, { name: "invalid operation", - op: types.BinaryOpAnd, // Not registered + op: physicalpb.BINARY_OP_ADD, // Not registered dataType: arrow.FixedWidthTypes.Boolean, expectError: true, }, { name: "invalid data type for operation", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, dataType: arrow.PrimitiveTypes.Int32, // Not registered expectError: true, }, @@ -207,49 +207,49 @@ func TestBinaryFunctionRegistry_GetForSignature(t *testing.T) { func TestBooleanComparisonFunctions(t *testing.T) { tests := []struct { name string - op types.BinaryOp + op physicalpb.BinaryOp lhs []bool rhs []bool expected []bool }{ { name: "boolean equality", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, lhs: []bool{true, false, true, false}, rhs: []bool{true, false, false, true}, expected: []bool{true, true, false, false}, }, { name: "boolean inequality", - op: types.BinaryOpNeq, + op: physicalpb.BINARY_OP_NEQ, lhs: []bool{true, false, true, false}, rhs: []bool{true, false, false, true}, expected: []bool{false, false, true, true}, }, { name: "boolean greater than", - op: types.BinaryOpGt, + op: physicalpb.BINARY_OP_GT, lhs: []bool{true, false, true, false}, rhs: []bool{false, true, true, false}, expected: []bool{true, false, false, false}, }, { name: "boolean greater than or equal", - op: types.BinaryOpGte, + op: physicalpb.BINARY_OP_GTE, lhs: []bool{true, false, true, false}, rhs: []bool{false, true, true, false}, expected: []bool{true, false, true, true}, }, { name: "boolean less than", - op: types.BinaryOpLt, + op: physicalpb.BINARY_OP_LT, lhs: []bool{true, false, true, false}, rhs: []bool{false, true, true, false}, expected: []bool{false, true, false, false}, }, { name: "boolean less than or equal", - op: types.BinaryOpLte, + op: physicalpb.BINARY_OP_LTE, lhs: []bool{true, false, true, false}, rhs: []bool{false, true, true, false}, expected: []bool{false, true, true, true}, @@ -276,49 +276,49 @@ func TestBooleanComparisonFunctions(t *testing.T) { func TestStringComparisonFunctions(t *testing.T) { tests := []struct { name string - op types.BinaryOp + op physicalpb.BinaryOp lhs []string rhs []string expected []bool }{ { name: "string equality", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, lhs: []string{"hello", "world", "test", ""}, rhs: []string{"hello", "world", "different", ""}, expected: []bool{true, true, false, true}, }, { name: "string inequality", - op: types.BinaryOpNeq, + op: physicalpb.BINARY_OP_NEQ, lhs: []string{"hello", "world", "test", ""}, rhs: []string{"hello", "world", "different", ""}, expected: []bool{false, false, true, false}, }, { name: "string greater than", - op: types.BinaryOpGt, + op: physicalpb.BINARY_OP_GT, lhs: []string{"b", "a", "z", "hello"}, rhs: []string{"a", "b", "a", "world"}, expected: []bool{true, false, true, false}, }, { name: "string greater than or equal", - op: types.BinaryOpGte, + op: physicalpb.BINARY_OP_GTE, lhs: []string{"b", "a", "z", "hello"}, rhs: []string{"a", "a", "a", "hello"}, expected: []bool{true, true, true, true}, }, { name: "string less than", - op: types.BinaryOpLt, + op: physicalpb.BINARY_OP_LT, lhs: []string{"a", "b", "a", "world"}, rhs: []string{"b", "a", "z", "hello"}, expected: []bool{true, false, true, false}, }, { name: "string less than or equal", - op: types.BinaryOpLte, + op: physicalpb.BINARY_OP_LTE, lhs: []string{"a", "a", "a", "hello"}, rhs: []string{"b", "a", "z", "hello"}, expected: []bool{true, true, true, true}, @@ -345,49 +345,49 @@ func TestStringComparisonFunctions(t *testing.T) { func TestIntegerComparisonFunctions(t *testing.T) { tests := []struct { name string - op types.BinaryOp + op physicalpb.BinaryOp lhs []int64 rhs []int64 expected []bool }{ { name: "int64 equality", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, lhs: []int64{1, 2, 3, 0, -1}, rhs: []int64{1, 3, 3, 0, 1}, expected: []bool{true, false, true, true, false}, }, { name: "int64 inequality", - op: types.BinaryOpNeq, + op: physicalpb.BINARY_OP_NEQ, lhs: []int64{1, 2, 3, 0, -1}, rhs: []int64{1, 3, 3, 0, 1}, expected: []bool{false, true, false, false, true}, }, { name: "int64 greater than", - op: types.BinaryOpGt, + op: physicalpb.BINARY_OP_GT, lhs: []int64{2, 1, 3, 0, -1}, rhs: []int64{1, 2, 3, 0, -2}, expected: []bool{true, false, false, false, true}, }, { name: "int64 greater than or equal", - op: types.BinaryOpGte, + op: physicalpb.BINARY_OP_GTE, lhs: []int64{2, 1, 3, 0, -1}, rhs: []int64{1, 1, 3, 0, -1}, expected: []bool{true, true, true, true, true}, }, { name: "int64 less than", - op: types.BinaryOpLt, + op: physicalpb.BINARY_OP_LT, lhs: []int64{1, 2, 3, 0, -2}, rhs: []int64{2, 1, 3, 0, -1}, expected: []bool{true, false, false, false, true}, }, { name: "int64 less than or equal", - op: types.BinaryOpLte, + op: physicalpb.BINARY_OP_LTE, lhs: []int64{1, 1, 3, 0, -1}, rhs: []int64{2, 1, 3, 0, -1}, expected: []bool{true, true, true, true, true}, @@ -414,49 +414,49 @@ func TestIntegerComparisonFunctions(t *testing.T) { func TestTimestampComparisonFunctions(t *testing.T) { tests := []struct { name string - op types.BinaryOp + op physicalpb.BinaryOp lhs []arrow.Timestamp rhs []arrow.Timestamp expected []bool }{ { name: "timestamp equality", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, lhs: []arrow.Timestamp{1, 2, 3, 0, 100}, rhs: []arrow.Timestamp{1, 3, 3, 0, 50}, expected: []bool{true, false, true, true, false}, }, { name: "timestamp inequality", - op: types.BinaryOpNeq, + op: physicalpb.BINARY_OP_NEQ, lhs: []arrow.Timestamp{1, 2, 3, 0, 100}, rhs: []arrow.Timestamp{1, 3, 3, 0, 50}, expected: []bool{false, true, false, false, true}, }, { name: "timestamp greater than", - op: types.BinaryOpGt, + op: physicalpb.BINARY_OP_GT, lhs: []arrow.Timestamp{2, 1, 3, 0, 100}, rhs: []arrow.Timestamp{1, 2, 3, 0, 50}, expected: []bool{true, false, false, false, true}, }, { name: "timestamp greater than or equal", - op: types.BinaryOpGte, + op: physicalpb.BINARY_OP_GTE, lhs: []arrow.Timestamp{2, 1, 3, 0, 100}, rhs: []arrow.Timestamp{1, 1, 3, 0, 100}, expected: []bool{true, true, true, true, true}, }, { name: "timestamp less than", - op: types.BinaryOpLt, + op: physicalpb.BINARY_OP_LT, lhs: []arrow.Timestamp{1, 2, 3, 0, 50}, rhs: []arrow.Timestamp{2, 1, 3, 0, 100}, expected: []bool{true, false, false, false, true}, }, { name: "timestamp less than or equal", - op: types.BinaryOpLte, + op: physicalpb.BINARY_OP_LTE, lhs: []arrow.Timestamp{1, 1, 3, 0, 100}, rhs: []arrow.Timestamp{2, 1, 3, 0, 100}, expected: []bool{true, true, true, true, true}, @@ -483,49 +483,49 @@ func TestTimestampComparisonFunctions(t *testing.T) { func TestFloat64ComparisonFunctions(t *testing.T) { tests := []struct { name string - op types.BinaryOp + op physicalpb.BinaryOp lhs []float64 rhs []float64 expected []bool }{ { name: "float64 equality", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, lhs: []float64{1.0, 2.5, 3.14, 0.0, -1.5}, rhs: []float64{1.0, 2.6, 3.14, 0.0, 1.5}, expected: []bool{true, false, true, true, false}, }, { name: "float64 inequality", - op: types.BinaryOpNeq, + op: physicalpb.BINARY_OP_NEQ, lhs: []float64{1.0, 2.5, 3.14, 0.0, -1.5}, rhs: []float64{1.0, 2.6, 3.14, 0.0, 1.5}, expected: []bool{false, true, false, false, true}, }, { name: "float64 greater than", - op: types.BinaryOpGt, + op: physicalpb.BINARY_OP_GT, lhs: []float64{2.0, 1.5, 3.14, 0.0, -1.0}, rhs: []float64{1.0, 2.0, 3.14, 0.0, -2.0}, expected: []bool{true, false, false, false, true}, }, { name: "float64 greater than or equal", - op: types.BinaryOpGte, + op: physicalpb.BINARY_OP_GTE, lhs: []float64{2.0, 1.5, 3.14, 0.0, -1.0}, rhs: []float64{1.0, 1.5, 3.14, 0.0, -1.0}, expected: []bool{true, true, true, true, true}, }, { name: "float64 less than", - op: types.BinaryOpLt, + op: physicalpb.BINARY_OP_LT, lhs: []float64{1.0, 2.0, 3.14, 0.0, -2.0}, rhs: []float64{2.0, 1.5, 3.14, 0.0, -1.0}, expected: []bool{true, false, false, false, true}, }, { name: "float64 less than or equal", - op: types.BinaryOpLte, + op: physicalpb.BINARY_OP_LTE, lhs: []float64{1.0, 1.5, 3.14, 0.0, -1.0}, rhs: []float64{2.0, 1.5, 3.14, 0.0, -1.0}, expected: []bool{true, true, true, true, true}, @@ -552,49 +552,49 @@ func TestFloat64ComparisonFunctions(t *testing.T) { func TestStringMatchingFunctions(t *testing.T) { tests := []struct { name string - op types.BinaryOp + op physicalpb.BinaryOp lhs []string rhs []string expected []bool }{ { name: "string contains", - op: types.BinaryOpMatchSubstr, + op: physicalpb.BINARY_OP_MATCH_SUBSTR, lhs: []string{"hello world", "test string", "foobar", ""}, rhs: []string{"world", "test", "baz", ""}, expected: []bool{true, true, false, true}, }, { name: "string does not contain", - op: types.BinaryOpNotMatchSubstr, + op: physicalpb.BINARY_OP_NOT_MATCH_SUBSTR, lhs: []string{"hello world", "test string", "foobar", ""}, rhs: []string{"world", "test", "baz", ""}, expected: []bool{false, false, true, false}, }, { name: "regex match", - op: types.BinaryOpMatchRe, + op: physicalpb.BINARY_OP_MATCH_RE, lhs: []string{"hello123", "test456", "abc", ""}, rhs: []string{"^hello\\d+$", "^\\d+", "^[a-z]+$", ".+"}, expected: []bool{true, false, true, false}, }, { name: "regex not match", - op: types.BinaryOpNotMatchRe, + op: physicalpb.BINARY_OP_NOT_MATCH_RE, lhs: []string{"hello123", "test456", "abc", ""}, rhs: []string{"^hello\\d+$", "^\\d+", "^[a-z]+$", ".+"}, expected: []bool{false, true, false, true}, }, { name: "case sensitive substring matching", - op: types.BinaryOpMatchSubstr, + op: physicalpb.BINARY_OP_MATCH_SUBSTR, lhs: []string{"Hello World", "TEST", "CaseSensitive"}, rhs: []string{"hello", "test", "Case"}, expected: []bool{false, false, true}, }, { name: "special characters in contains", - op: types.BinaryOpMatchSubstr, + op: physicalpb.BINARY_OP_MATCH_SUBSTR, lhs: []string{"hello@world.com", "test[123]", "foo.bar", ""}, rhs: []string{"@world", "[123]", ".", ""}, expected: []bool{true, true, true, true}, @@ -621,14 +621,14 @@ func TestStringMatchingFunctions(t *testing.T) { func TestNullValueHandling(t *testing.T) { tests := []struct { name string - op types.BinaryOp + op physicalpb.BinaryOp dataType arrow.DataType setup func() (arrow.Array, arrow.Array) expected []bool }{ { name: "boolean with nulls", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, dataType: arrow.FixedWidthTypes.Boolean, setup: func() (arrow.Array, arrow.Array) { lhs := createBoolArray([]bool{true, false, true}, []bool{false, true, false}) @@ -639,7 +639,7 @@ func TestNullValueHandling(t *testing.T) { }, { name: "string with nulls", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, dataType: arrow.BinaryTypes.String, setup: func() (arrow.Array, arrow.Array) { lhs := createStringArray([]string{"hello", "world", "test"}, []bool{false, true, false}) @@ -650,7 +650,7 @@ func TestNullValueHandling(t *testing.T) { }, { name: "int64 with nulls", - op: types.BinaryOpGt, + op: physicalpb.BINARY_OP_GT, dataType: arrow.PrimitiveTypes.Int64, setup: func() (arrow.Array, arrow.Array) { lhs := createInt64Array([]int64{5, 10, 15}, []bool{false, true, false}) @@ -680,13 +680,13 @@ func TestNullValueHandling(t *testing.T) { func TestArrayLengthMismatch(t *testing.T) { tests := []struct { name string - op types.BinaryOp + op physicalpb.BinaryOp dataType arrow.DataType setup func() (arrow.Array, arrow.Array) }{ { name: "boolean length mismatch", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, dataType: arrow.FixedWidthTypes.Boolean, setup: func() (arrow.Array, arrow.Array) { lhs := createBoolArray([]bool{true, false}, nil) @@ -696,7 +696,7 @@ func TestArrayLengthMismatch(t *testing.T) { }, { name: "string length mismatch", - op: types.BinaryOpEq, + op: physicalpb.BINARY_OP_EQ, dataType: arrow.BinaryTypes.String, setup: func() (arrow.Array, arrow.Array) { lhs := createStringArray([]string{"hello"}, nil) @@ -706,7 +706,7 @@ func TestArrayLengthMismatch(t *testing.T) { }, { name: "int64 length mismatch", - op: types.BinaryOpGt, + op: physicalpb.BINARY_OP_GT, dataType: arrow.PrimitiveTypes.Int64, setup: func() (arrow.Array, arrow.Array) { lhs := createInt64Array([]int64{1, 2, 3}, nil) @@ -735,7 +735,7 @@ func TestRegexCompileError(t *testing.T) { lhs := createStringArray([]string{"hello", "world"}, nil) rhs := createStringArray([]string{"[", "("}, nil) // Invalid regex patterns - fn, err := binaryFunctions.GetForSignature(types.BinaryOpMatchRe, arrow.BinaryTypes.String) + fn, err := binaryFunctions.GetForSignature(physicalpb.BINARY_OP_MATCH_RE, arrow.BinaryTypes.String) require.NoError(t, err) _, err = fn.Evaluate(lhs, rhs) @@ -773,7 +773,7 @@ func TestEmptyArrays(t *testing.T) { lhs := createStringArray([]string{}, nil) rhs := createStringArray([]string{}, nil) - fn, err := binaryFunctions.GetForSignature(types.BinaryOpEq, arrow.BinaryTypes.String) + fn, err := binaryFunctions.GetForSignature(physicalpb.BINARY_OP_EQ, arrow.BinaryTypes.String) require.NoError(t, err) result, err := fn.Evaluate(lhs, rhs) diff --git a/pkg/engine/internal/executor/limit_test.go b/pkg/engine/internal/executor/limit_test.go index e7b11237ec9ce..584b5be860080 100644 --- a/pkg/engine/internal/executor/limit_test.go +++ b/pkg/engine/internal/executor/limit_test.go @@ -7,7 +7,7 @@ import ( "github.com/apache/arrow-go/v18/arrow" "github.com/stretchr/testify/require" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) @@ -17,14 +17,14 @@ func TestExecuteLimit(t *testing.T) { t.Run("with no inputs", func(t *testing.T) { ctx := t.Context() - pipeline := c.executeLimit(ctx, &physical.Limit{}, nil) + pipeline := c.executeLimit(ctx, &physicalpb.Limit{}, nil) _, err := pipeline.Read(ctx) require.Equal(t, EOF, err) }) t.Run("with multiple inputs", func(t *testing.T) { ctx := t.Context() - pipeline := c.executeLimit(ctx, &physical.Limit{}, []Pipeline{emptyPipeline(), emptyPipeline()}) + pipeline := c.executeLimit(ctx, &physicalpb.Limit{}, []Pipeline{emptyPipeline(), emptyPipeline()}) _, err := pipeline.Read(ctx) require.Error(t, err) require.Contains(t, err.Error(), "limit expects exactly one input, got 2") @@ -43,7 +43,7 @@ func TestExecuteLimit(t *testing.T) { source := NewBufferedPipeline(record) // Execute limit with skip=1 and fetch=1 - limit := &physical.Limit{Skip: 1, Fetch: 1} + limit := &physicalpb.Limit{Skip: 1, Fetch: 1} pipeline := c.executeLimit(ctx, limit, []Pipeline{source}) defer pipeline.Close() @@ -86,7 +86,7 @@ func TestExecuteLimit(t *testing.T) { // Create limit pipeline that skips 2 and fetches 3 // Should return C from batch1, and D,E from batch2 - limit := &physical.Limit{Skip: 2, Fetch: 3} + limit := &physicalpb.Limit{Skip: 2, Fetch: 3} pipeline := c.executeLimit(ctx, limit, []Pipeline{source}) defer pipeline.Close() @@ -221,7 +221,7 @@ func TestLimit(t *testing.T) { c := &Context{ batchSize: tt.batchSize, } - limit := &physical.Limit{ + limit := &physicalpb.Limit{ Skip: tt.offset, Fetch: tt.limit, } diff --git a/pkg/engine/internal/executor/parse.go b/pkg/engine/internal/executor/parse.go index 8ce953e76196b..e9149209da6d7 100644 --- a/pkg/engine/internal/executor/parse.go +++ b/pkg/engine/internal/executor/parse.go @@ -10,12 +10,12 @@ import ( "github.com/apache/arrow-go/v18/arrow/array" "github.com/apache/arrow-go/v18/arrow/memory" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) -func NewParsePipeline(parse *physical.ParseNode, input Pipeline) *GenericPipeline { +func NewParsePipeline(parse *physicalpb.Parse, input Pipeline) *GenericPipeline { return newGenericPipeline(func(ctx context.Context, inputs []Pipeline) (arrow.Record, error) { // Pull the next item from the input pipeline input := inputs[0] @@ -37,13 +37,13 @@ func NewParsePipeline(parse *physical.ParseNode, input Pipeline) *GenericPipelin var headers []string var parsedColumns []arrow.Array - switch parse.Kind { - case physical.ParserLogfmt: + switch parse.Operation { + case physicalpb.PARSE_OP_LOGFMT: headers, parsedColumns = buildLogfmtColumns(stringCol, parse.RequestedKeys) - case physical.ParserJSON: + case physicalpb.PARSE_OP_JSON: headers, parsedColumns = buildJSONColumns(stringCol, parse.RequestedKeys) default: - return nil, fmt.Errorf("unsupported parser kind: %v", parse.Kind) + return nil, fmt.Errorf("unsupported parser kind: %v", parse.Operation) } // Build new schema with original fields plus parsed fields @@ -53,9 +53,9 @@ func NewParsePipeline(parse *physical.ParseNode, input Pipeline) *GenericPipelin newFields = append(newFields, schema.Field(i)) } for _, header := range headers { - ct := types.ColumnTypeParsed + ct := physicalpb.COLUMN_TYPE_PARSED if header == semconv.ColumnIdentError.ShortName() || header == semconv.ColumnIdentErrorDetails.ShortName() { - ct = types.ColumnTypeGenerated + ct = physicalpb.COLUMN_TYPE_GENERATED } ident := semconv.NewIdentifier(header, ct, types.Loki.String) newFields = append(newFields, semconv.FieldFromIdent(ident, true)) diff --git a/pkg/engine/internal/executor/parse_test.go b/pkg/engine/internal/executor/parse_test.go index bdde3fc27c167..28ed8af4abc37 100644 --- a/pkg/engine/internal/executor/parse_test.go +++ b/pkg/engine/internal/executor/parse_test.go @@ -7,7 +7,7 @@ import ( "github.com/apache/arrow-go/v18/arrow" "github.com/stretchr/testify/require" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/util/arrowtest" @@ -283,8 +283,8 @@ func TestNewParsePipeline_logfmt(t *testing.T) { ) // Create ParseNode requesting "level" field - parseNode := &physical.ParseNode{ - Kind: physical.ParserLogfmt, + parseNode := &physicalpb.Parse{ + Operation: physicalpb.PARSE_OP_LOGFMT, RequestedKeys: tt.requestedKeys, } @@ -705,8 +705,8 @@ func TestNewParsePipeline_JSON(t *testing.T) { ) // Create ParseNode for JSON parsing - parseNode := &physical.ParseNode{ - Kind: physical.ParserJSON, + parseNode := &physicalpb.Parse{ + Operation: physicalpb.PARSE_OP_JSON, RequestedKeys: tt.requestedKeys, } diff --git a/pkg/engine/internal/executor/project.go b/pkg/engine/internal/executor/project.go index a9d00311dd4f7..013ceedbe0c9d 100644 --- a/pkg/engine/internal/executor/project.go +++ b/pkg/engine/internal/executor/project.go @@ -8,29 +8,28 @@ import ( "github.com/apache/arrow-go/v18/arrow" "github.com/apache/arrow-go/v18/arrow/array" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" - "github.com/grafana/loki/v3/pkg/engine/internal/types" ) -func NewProjectPipeline(input Pipeline, proj *physical.Projection, evaluator *expressionEvaluator) (Pipeline, error) { +func NewProjectPipeline(input Pipeline, proj *physicalpb.Projection, evaluator *expressionEvaluator) (Pipeline, error) { // Shortcut for ALL=true DROP=false EXPAND=false if proj.All && !proj.Drop && !proj.Expand { return input, nil } // Get the column names from the projection expressions - colRefs := make([]types.ColumnRef, 0, len(proj.Expressions)) - mathExprs := make([]physical.Expression, 0, len(proj.Expressions)) + colRefs := make([]physicalpb.ColumnExpression, 0, len(proj.Expressions)) + mathExprs := make([]physicalpb.Expression, 0, len(proj.Expressions)) for i, expr := range proj.Expressions { - switch expr := expr.(type) { - case *physical.ColumnExpr: - colRefs = append(colRefs, expr.Ref) - case *physical.UnaryExpr: - mathExprs = append(mathExprs, expr) - case *physical.BinaryExpr: - mathExprs = append(mathExprs, expr) + switch expr := expr.Kind.(type) { + case *physicalpb.Expression_ColumnExpression: + colRefs = append(colRefs, *expr.ColumnExpression) + case *physicalpb.Expression_UnaryExpression: + mathExprs = append(mathExprs, *expr.UnaryExpression.ToExpression()) + case *physicalpb.Expression_BinaryExpression: + mathExprs = append(mathExprs, *expr.BinaryExpression.ToExpression()) default: return nil, fmt.Errorf("projection expression %d is unsupported", i) } @@ -43,14 +42,14 @@ func NewProjectPipeline(input Pipeline, proj *physical.Projection, evaluator *ex // Create KEEP projection pipeline: // Drop all columns except the ones referenced in proj.Expressions. if !proj.All && !proj.Drop && !proj.Expand { - return newKeepPipeline(colRefs, func(refs []types.ColumnRef, ident *semconv.Identifier) bool { - return slices.ContainsFunc(refs, func(ref types.ColumnRef) bool { + return newKeepPipeline(colRefs, func(refs []physicalpb.ColumnExpression, ident *semconv.Identifier) bool { + return slices.ContainsFunc(refs, func(ref physicalpb.ColumnExpression) bool { // Keep all of the ambiguous columns - if ref.Type == types.ColumnTypeAmbiguous { - return ref.Column == ident.ShortName() + if ref.Type == physicalpb.COLUMN_TYPE_AMBIGUOUS { + return ref.Name == ident.ShortName() } // Keep only if type matches - return ref.Column == ident.ShortName() && ref.Type == ident.ColumnType() + return ref.Name == ident.ShortName() && ref.Type == ident.ColumnTypePhys() }) }, input) } @@ -58,14 +57,14 @@ func NewProjectPipeline(input Pipeline, proj *physical.Projection, evaluator *ex // Create DROP projection pipeline: // Keep all columns except the ones referenced in proj.Expressions. if proj.All && proj.Drop { - return newKeepPipeline(colRefs, func(refs []types.ColumnRef, ident *semconv.Identifier) bool { - return !slices.ContainsFunc(refs, func(ref types.ColumnRef) bool { + return newKeepPipeline(colRefs, func(refs []physicalpb.ColumnExpression, ident *semconv.Identifier) bool { + return !slices.ContainsFunc(refs, func(ref physicalpb.ColumnExpression) bool { // Drop all of the ambiguous columns - if ref.Type == types.ColumnTypeAmbiguous { - return ref.Column == ident.ShortName() + if ref.Type == physicalpb.COLUMN_TYPE_AMBIGUOUS { + return ref.Name == ident.ShortName() } // Drop only if type matches - return ref.Column == ident.ShortName() && ref.Type == ident.ColumnType() + return ref.Name == ident.ShortName() && ref.Type == ident.ColumnTypePhys() }) }, input) } @@ -80,7 +79,7 @@ func NewProjectPipeline(input Pipeline, proj *physical.Projection, evaluator *ex return nil, errNotImplemented } -func newKeepPipeline(colRefs []types.ColumnRef, keepFunc func([]types.ColumnRef, *semconv.Identifier) bool, input Pipeline) (*GenericPipeline, error) { +func newKeepPipeline(colRefs []physicalpb.ColumnExpression, keepFunc func([]physicalpb.ColumnExpression, *semconv.Identifier) bool, input Pipeline) (*GenericPipeline, error) { return newGenericPipeline(func(ctx context.Context, inputs []Pipeline) (arrow.Record, error) { if len(inputs) != 1 { return nil, fmt.Errorf("expected 1 input, got %d", len(inputs)) @@ -111,7 +110,7 @@ func newKeepPipeline(colRefs []types.ColumnRef, keepFunc func([]types.ColumnRef, }, input), nil } -func newExpandPipeline(expr physical.Expression, evaluator *expressionEvaluator, input Pipeline) (*GenericPipeline, error) { +func newExpandPipeline(expr physicalpb.Expression, evaluator *expressionEvaluator, input Pipeline) (*GenericPipeline, error) { return newGenericPipeline(func(ctx context.Context, inputs []Pipeline) (arrow.Record, error) { if len(inputs) != 1 { return nil, fmt.Errorf("expected 1 input, got %d", len(inputs)) diff --git a/pkg/engine/internal/executor/project_test.go b/pkg/engine/internal/executor/project_test.go index b3cf52636d0dc..1ce3e2c7168cb 100644 --- a/pkg/engine/internal/executor/project_test.go +++ b/pkg/engine/internal/executor/project_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/util/arrowtest" @@ -30,15 +31,16 @@ func TestNewProjectPipeline(t *testing.T) { inputPipeline := NewBufferedPipeline(inputRecord) // Create projection columns (just the "name" column) - columns := []physical.Expression{ - &physical.ColumnExpr{ - Ref: createColumnRef("name"), - }, + columns := []*physicalpb.Expression{ + (&physicalpb.ColumnExpression{ + Name: "name", + Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), } // Create project pipeline e := newExpressionEvaluator() - projectPipeline, err := NewProjectPipeline(inputPipeline, &physical.Projection{Expressions: columns}, &e) + projectPipeline, err := NewProjectPipeline(inputPipeline, &physicalpb.Projection{Expressions: columns}, &e) require.NoError(t, err) // Create expected output @@ -65,18 +67,20 @@ func TestNewProjectPipeline(t *testing.T) { inputPipeline := NewBufferedPipeline(inputRecord) // Create projection columns (both "name" and "city" columns) - columns := []physical.Expression{ - &physical.ColumnExpr{ - Ref: createColumnRef("name"), - }, - &physical.ColumnExpr{ - Ref: createColumnRef("city"), - }, + columns := []*physicalpb.Expression{ + (&physicalpb.ColumnExpression{ + Name: "name", + Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), + (&physicalpb.ColumnExpression{ + Name: "city", + Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), } // Create project pipeline e := newExpressionEvaluator() - projectPipeline, err := NewProjectPipeline(inputPipeline, &physical.Projection{Expressions: columns}, &e) + projectPipeline, err := NewProjectPipeline(inputPipeline, &physicalpb.Projection{Expressions: columns}, &e) require.NoError(t, err) // Create expected output @@ -109,18 +113,20 @@ func TestNewProjectPipeline(t *testing.T) { inputPipeline := NewBufferedPipeline(inputRecord1, inputRecord2) // Create projection columns - columns := []physical.Expression{ - &physical.ColumnExpr{ - Ref: createColumnRef("name"), - }, - &physical.ColumnExpr{ - Ref: createColumnRef("age"), - }, + columns := []*physicalpb.Expression{ + (&physicalpb.ColumnExpression{ + Name: "name", + Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), + (&physicalpb.ColumnExpression{ + Name: "age", + Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression(), } // Create project pipeline e := newExpressionEvaluator() - projectPipeline, err := NewProjectPipeline(inputPipeline, &physical.Projection{Expressions: columns}, &e) + projectPipeline, err := NewProjectPipeline(inputPipeline, &physicalpb.Projection{Expressions: columns}, &e) require.NoError(t, err) // Create expected output also split across multiple records @@ -161,13 +167,13 @@ Dave,40 for _, tc := range []struct { name string - columns []physical.Expression + columns []*physicalpb.Expression expectedFields []arrow.Field }{ { name: "single column", - columns: []physical.Expression{ - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "service", Type: types.ColumnTypeAmbiguous}}, + columns: []*physicalpb.Expression{ + (&physicalpb.ColumnExpression{Name: "service", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), }, expectedFields: []arrow.Field{ semconv.FieldFromFQN("int64.metadata.count", false), @@ -176,8 +182,8 @@ Dave,40 }, { name: "single ambiguous column", - columns: []physical.Expression{ - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "count", Type: types.ColumnTypeAmbiguous}}, + columns: []*physicalpb.Expression{ + (&physicalpb.ColumnExpression{Name: "count", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), }, expectedFields: []arrow.Field{ semconv.FieldFromFQN("utf8.builtin.service", false), @@ -185,8 +191,8 @@ Dave,40 }, { name: "single non-ambiguous column", - columns: []physical.Expression{ - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "count", Type: types.ColumnTypeMetadata}}, + columns: []*physicalpb.Expression{ + (&physicalpb.ColumnExpression{Name: "count", Type: physicalpb.COLUMN_TYPE_METADATA}).ToExpression(), }, expectedFields: []arrow.Field{ semconv.FieldFromFQN("utf8.builtin.service", false), @@ -195,9 +201,9 @@ Dave,40 }, { name: "multiple columns", - columns: []physical.Expression{ - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "service", Type: types.ColumnTypeBuiltin}}, - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "count", Type: types.ColumnTypeParsed}}, + columns: []*physicalpb.Expression{ + (&physicalpb.ColumnExpression{Name: "service", Type: physicalpb.COLUMN_TYPE_BUILTIN}).ToExpression(), + (&physicalpb.ColumnExpression{Name: "count", Type: physicalpb.COLUMN_TYPE_PARSED}).ToExpression(), }, expectedFields: []arrow.Field{ semconv.FieldFromFQN("int64.metadata.count", false), @@ -205,8 +211,8 @@ Dave,40 }, { name: "non existent columns", - columns: []physical.Expression{ - &physical.ColumnExpr{Ref: types.ColumnRef{Column: "__error__", Type: types.ColumnTypeAmbiguous}}, + columns: []*physicalpb.Expression{ + (&physicalpb.ColumnExpression{Name: "__error__", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), }, expectedFields: []arrow.Field{ semconv.FieldFromFQN("utf8.builtin.service", false), @@ -220,7 +226,7 @@ Dave,40 input := NewArrowtestPipeline(schema, rows) // Create project pipeline - proj := &physical.Projection{ + proj := &physicalpb.Projection{ Expressions: tc.columns, All: true, Drop: true, @@ -246,7 +252,7 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithCast(t *testing.T) { name string schema *arrow.Schema input arrowtest.Rows - columnExprs []physical.Expression + columnExprs []*physicalpb.Expression expectedFields int expectedOutput arrowtest.Rows }{ @@ -262,11 +268,11 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithCast(t *testing.T) { {"utf8.builtin.message": "slow request", "utf8.metadata.status_code": "200", "utf8.label.response_time": "500"}, {"utf8.builtin.message": "error occurred", "utf8.metadata.status_code": "500", "utf8.label.response_time": "100"}, }, - columnExprs: []physical.Expression{ - &physical.UnaryExpr{ - Op: types.UnaryOpCastFloat, - Left: &physical.ColumnExpr{Ref: createAmbiguousColumnRef("response_time")}, - }, + columnExprs: []*physicalpb.Expression{ + (&physicalpb.UnaryExpression{ + Op: physicalpb.UNARY_OP_CAST_FLOAT, + Value: (&physicalpb.ColumnExpression{Name: "response_time", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), + }).ToExpression(), }, expectedFields: 4, // 4 columns: message, status_code, response_time, value expectedOutput: arrowtest.Rows{ @@ -286,11 +292,11 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithCast(t *testing.T) { {"utf8.builtin.message": "large upload", "utf8.parsed.data_size": "5MiB"}, {"utf8.builtin.message": "small file", "utf8.parsed.data_size": "512B"}, }, - columnExprs: []physical.Expression{ - &physical.UnaryExpr{ - Op: types.UnaryOpCastBytes, - Left: &physical.ColumnExpr{Ref: createAmbiguousColumnRef("data_size")}, - }, + columnExprs: []*physicalpb.Expression{ + (&physicalpb.UnaryExpression{ + Op: physicalpb.UNARY_OP_CAST_BYTES, + Value: (&physicalpb.ColumnExpression{Name: "data_size", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), + }).ToExpression(), }, expectedFields: 3, // 4 columns: message, data_size, value expectedOutput: arrowtest.Rows{ @@ -311,11 +317,11 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithCast(t *testing.T) { {"utf8.builtin.message": "fast request", "utf8.metadata.status_code": "200", "utf8.parsed.request_duration": "250ms"}, {"utf8.builtin.message": "slow request", "utf8.metadata.status_code": "500", "utf8.parsed.request_duration": "30s"}, }, - columnExprs: []physical.Expression{ - &physical.UnaryExpr{ - Op: types.UnaryOpCastDuration, - Left: &physical.ColumnExpr{Ref: createAmbiguousColumnRef("request_duration")}, - }, + columnExprs: []*physicalpb.Expression{ + (&physicalpb.UnaryExpression{ + Op: physicalpb.UNARY_OP_CAST_DURATION, + Value: (&physicalpb.ColumnExpression{Name: "request_duration", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), + }).ToExpression(), }, expectedFields: 4, // 4 columns: message, status_code, request_duration, value expectedOutput: arrowtest.Rows{ @@ -336,11 +342,11 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithCast(t *testing.T) { {"utf8.builtin.message": "short timeout", "utf8.metadata.status_code": "200", "utf8.parsed.timeout": "10s"}, {"utf8.builtin.message": "long timeout", "utf8.metadata.status_code": "200", "utf8.parsed.timeout": "1h"}, }, - columnExprs: []physical.Expression{ - &physical.UnaryExpr{ - Op: types.UnaryOpCastDuration, - Left: &physical.ColumnExpr{Ref: createAmbiguousColumnRef("timeout")}, - }, + columnExprs: []*physicalpb.Expression{ + (&physicalpb.UnaryExpression{ + Op: physicalpb.UNARY_OP_CAST_DURATION, + Value: (&physicalpb.ColumnExpression{Name: "timeout", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), + }).ToExpression(), }, expectedFields: 4, // 4 columns: message, status_code, timeout, value expectedOutput: arrowtest.Rows{ @@ -362,11 +368,11 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithCast(t *testing.T) { {"utf8.builtin.message": "invalid bytes", "utf8.parsed.mixed_values": "invalid_bytes"}, {"utf8.builtin.message": "empty string", "utf8.parsed.mixed_values": ""}, }, - columnExprs: []physical.Expression{ - &physical.UnaryExpr{ - Op: types.UnaryOpCastFloat, - Left: &physical.ColumnExpr{Ref: createAmbiguousColumnRef("mixed_values")}, - }, + columnExprs: []*physicalpb.Expression{ + (&physicalpb.UnaryExpression{ + Op: physicalpb.UNARY_OP_CAST_FLOAT, + Value: (&physicalpb.ColumnExpression{Name: "mixed_values", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), + }).ToExpression(), }, expectedFields: 5, expectedOutput: arrowtest.Rows{ @@ -404,11 +410,11 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithCast(t *testing.T) { {"utf8.builtin.message": "only whitespace", "utf8.parsed.edge_values": " "}, {"utf8.builtin.message": "mixed text and numbers", "utf8.parsed.edge_values": "123abc"}, }, - columnExprs: []physical.Expression{ - &physical.UnaryExpr{ - Op: types.UnaryOpCastFloat, - Left: &physical.ColumnExpr{Ref: createAmbiguousColumnRef("edge_values")}, - }, + columnExprs: []*physicalpb.Expression{ + (&physicalpb.UnaryExpression{ + Op: physicalpb.UNARY_OP_CAST_FLOAT, + Value: (&physicalpb.ColumnExpression{Name: "edge_values", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), + }).ToExpression(), }, expectedFields: 5, expectedOutput: arrowtest.Rows{ @@ -445,11 +451,11 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithCast(t *testing.T) { {"utf8.builtin.message": "fractional duration", "utf8.parsed.duration_values": "1.5s"}, {"utf8.builtin.message": "invalid duration", "utf8.parsed.duration_values": "5 seconds"}, // space makes it invalid }, - columnExprs: []physical.Expression{ - &physical.UnaryExpr{ - Op: types.UnaryOpCastDuration, - Left: &physical.ColumnExpr{Ref: createAmbiguousColumnRef("duration_values")}, - }, + columnExprs: []*physicalpb.Expression{ + (&physicalpb.UnaryExpression{ + Op: physicalpb.UNARY_OP_CAST_DURATION, + Value: (&physicalpb.ColumnExpression{Name: "duration_values", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), + }).ToExpression(), }, expectedFields: 5, expectedOutput: arrowtest.Rows{ @@ -486,7 +492,7 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithCast(t *testing.T) { e := newExpressionEvaluator() pipeline, err := NewProjectPipeline( input, - &physical.Projection{ + &physicalpb.Projection{ Expressions: tt.columnExprs, Expand: true, All: true, @@ -537,18 +543,16 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithBinOn(t *testing.T) { input1 := NewArrowtestPipeline(schema, rowsPipeline1...) // value / 10 - projection := &physical.Projection{ - Expressions: []physical.Expression{ - &physical.BinaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: types.ColumnNameGeneratedValue, - Type: types.ColumnTypeGenerated, - }, - }, - Right: physical.NewLiteral(float64(10)), - Op: types.BinaryOpDiv, - }, + projection := &physicalpb.Projection{ + Expressions: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{ + Name: types.ColumnNameGeneratedValue, + Type: physicalpb.COLUMN_TYPE_GENERATED, + }).ToExpression(), + Right: physical.NewLiteral(float64(10)).ToExpression(), + Op: physicalpb.BINARY_OP_DIV, + }).ToExpression(), }, All: true, Expand: true, @@ -599,26 +603,24 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithBinOn(t *testing.T) { input1 := NewArrowtestPipeline(schema, rowsPipeline1...) // value * 10 + 100 / 10 - projection := &physical.Projection{ - Expressions: []physical.Expression{ - &physical.BinaryExpr{ - Left: &physical.BinaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: types.ColumnNameGeneratedValue, - Type: types.ColumnTypeGenerated, - }, - }, - Right: physical.NewLiteral(float64(10)), - Op: types.BinaryOpMul, - }, - Right: &physical.BinaryExpr{ - Left: physical.NewLiteral(float64(100)), - Right: physical.NewLiteral(float64(10)), - Op: types.BinaryOpDiv, - }, - Op: types.BinaryOpAdd, - }, + projection := &physicalpb.Projection{ + Expressions: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: (&physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{ + Name: types.ColumnNameGeneratedValue, + Type: physicalpb.COLUMN_TYPE_GENERATED, + }).ToExpression(), + Right: physical.NewLiteral(float64(10)).ToExpression(), + Op: physicalpb.BINARY_OP_MUL, + }).ToExpression(), + Right: (&physicalpb.BinaryExpression{ + Left: physical.NewLiteral(float64(100)).ToExpression(), + Right: physical.NewLiteral(float64(10)).ToExpression(), + Op: physicalpb.BINARY_OP_DIV, + }).ToExpression(), + Op: physicalpb.BINARY_OP_ADD, + }).ToExpression(), }, All: true, Expand: true, @@ -672,23 +674,19 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithBinOn(t *testing.T) { input1 := NewArrowtestPipeline(schema, rowsPipeline1...) // value_left / value_right - projection := &physical.Projection{ - Expressions: []physical.Expression{ - &physical.BinaryExpr{ - Left: &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "value_left", - Type: types.ColumnTypeGenerated, - }, - }, - Right: &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "value_right", - Type: types.ColumnTypeGenerated, - }, - }, - Op: types.BinaryOpDiv, - }, + projection := &physicalpb.Projection{ + Expressions: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{ + Name: "value_left", + Type: physicalpb.COLUMN_TYPE_GENERATED, + }).ToExpression(), + Right: (&physicalpb.ColumnExpression{ + Name: "value_right", + Type: physicalpb.COLUMN_TYPE_GENERATED, + }).ToExpression(), + Op: physicalpb.BINARY_OP_DIV, + }).ToExpression(), }, All: true, Expand: true, @@ -715,19 +713,3 @@ func TestNewProjectPipeline_ProjectionFunction_ExpandWithBinOn(t *testing.T) { require.ElementsMatch(t, expect, rows) }) } - -// Helper to create a column reference -func createColumnRef(name string) types.ColumnRef { - return types.ColumnRef{ - Column: name, - Type: types.ColumnTypeBuiltin, - } -} - -// Helper to create a column reference -func createAmbiguousColumnRef(name string) types.ColumnRef { - return types.ColumnRef{ - Column: name, - Type: types.ColumnTypeAmbiguous, - } -} diff --git a/pkg/engine/internal/executor/range_aggregation.go b/pkg/engine/internal/executor/range_aggregation.go index a158d88698c9c..5ce9c29a0f048 100644 --- a/pkg/engine/internal/executor/range_aggregation.go +++ b/pkg/engine/internal/executor/range_aggregation.go @@ -11,28 +11,28 @@ import ( "github.com/apache/arrow-go/v18/arrow" "github.com/apache/arrow-go/v18/arrow/array" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) type rangeAggregationOptions struct { - partitionBy []physical.ColumnExpression + partitionBy []*physicalpb.ColumnExpression // start and end timestamps are equal for instant queries. startTs time.Time // start timestamp of the query endTs time.Time // end timestamp of the query rangeInterval time.Duration // range interval step time.Duration // step used for range queries - operation types.RangeAggregationType + operation physicalpb.AggregateRangeOp } var ( // rangeAggregationOperations holds the mapping of range aggregation types to operations for an aggregator. - rangeAggregationOperations = map[types.RangeAggregationType]aggregationOperation{ - types.RangeAggregationTypeSum: aggregationOperationSum, - types.RangeAggregationTypeCount: aggregationOperationCount, - types.RangeAggregationTypeMax: aggregationOperationMax, - types.RangeAggregationTypeMin: aggregationOperationMin, + rangeAggregationOperations = map[physicalpb.AggregateRangeOp]aggregationOperation{ + physicalpb.AGGREGATE_RANGE_OP_SUM: aggregationOperationSum, + physicalpb.AGGREGATE_RANGE_OP_COUNT: aggregationOperationCount, + physicalpb.AGGREGATE_RANGE_OP_MAX: aggregationOperationMax, + physicalpb.AGGREGATE_RANGE_OP_MIN: aggregationOperationMin, } ) @@ -121,18 +121,14 @@ func (r *rangeAggregationPipeline) Read(ctx context.Context) (arrow.Record, erro // - Add toggle to return partial results on Read() call instead of returning only after exhausting all inputs. func (r *rangeAggregationPipeline) read(ctx context.Context) (arrow.Record, error) { var ( - tsColumnExpr = &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: types.ColumnNameBuiltinTimestamp, - Type: types.ColumnTypeBuiltin, - }, + tsColumnExpr = &physicalpb.ColumnExpression{ + Name: types.ColumnNameBuiltinTimestamp, + Type: physicalpb.COLUMN_TYPE_BUILTIN, } // timestamp column expression - valColumnExpr = &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: types.ColumnNameGeneratedValue, - Type: types.ColumnTypeGenerated, - }, + valColumnExpr = &physicalpb.ColumnExpression{ + Name: types.ColumnNameGeneratedValue, + Type: physicalpb.COLUMN_TYPE_GENERATED, } // value column expression // reused on each row read @@ -158,7 +154,7 @@ func (r *rangeAggregationPipeline) read(ctx context.Context) (arrow.Record, erro // extract all the columns that are used for partitioning arrays := make([]*array.String, 0, len(r.opts.partitionBy)) for _, columnExpr := range r.opts.partitionBy { - vec, err := r.evaluator.eval(columnExpr, record) + vec, err := r.evaluator.eval(*columnExpr.ToExpression(), record) if err != nil { return nil, err } @@ -172,7 +168,7 @@ func (r *rangeAggregationPipeline) read(ctx context.Context) (arrow.Record, erro } // extract timestamp column to check if the entry is in range - tsVec, err := r.evaluator.eval(tsColumnExpr, record) + tsVec, err := r.evaluator.eval(*tsColumnExpr.ToExpression(), record) if err != nil { return nil, err } @@ -180,8 +176,8 @@ func (r *rangeAggregationPipeline) read(ctx context.Context) (arrow.Record, erro // no need to extract value column for COUNT aggregation var valArr *array.Float64 - if r.opts.operation != types.RangeAggregationTypeCount { - valVec, err := r.evaluator.eval(valColumnExpr, record) + if r.opts.operation != physicalpb.AGGREGATE_RANGE_OP_COUNT { + valVec, err := r.evaluator.eval(*valColumnExpr.ToExpression(), record) if err != nil { return nil, err } @@ -201,7 +197,7 @@ func (r *rangeAggregationPipeline) read(ctx context.Context) (arrow.Record, erro } var value float64 - if r.opts.operation != types.RangeAggregationTypeCount { + if r.opts.operation != physicalpb.AGGREGATE_RANGE_OP_COUNT { value = valArr.Value(row) } diff --git a/pkg/engine/internal/executor/range_aggregation_test.go b/pkg/engine/internal/executor/range_aggregation_test.go index bee8b1b3ce0a4..a386821281e0c 100644 --- a/pkg/engine/internal/executor/range_aggregation_test.go +++ b/pkg/engine/internal/executor/range_aggregation_test.go @@ -8,9 +8,8 @@ import ( "github.com/apache/arrow-go/v18/arrow" "github.com/stretchr/testify/require" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" - "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/util/arrowtest" ) @@ -56,24 +55,20 @@ func TestRangeAggregationPipeline_instant(t *testing.T) { } opts := rangeAggregationOptions{ - partitionBy: []physical.ColumnExpression{ - &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "env", - Type: types.ColumnTypeAmbiguous, - }, + partitionBy: []*physicalpb.ColumnExpression{ + { + Name: "env", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, }, - &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "service", - Type: types.ColumnTypeAmbiguous, - }, + { + Name: "service", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, }, }, startTs: time.Unix(20, 0).UTC(), endTs: time.Unix(20, 0).UTC(), rangeInterval: 10 * time.Second, - operation: types.RangeAggregationTypeCount, + operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, } inputA := NewArrowtestPipeline(schema, rowsPipelineA...) @@ -138,18 +133,14 @@ func TestRangeAggregationPipeline(t *testing.T) { }} ) - partitionBy := []physical.ColumnExpression{ - &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "env", - Type: types.ColumnTypeAmbiguous, - }, + partitionBy := []*physicalpb.ColumnExpression{ + { + Name: "env", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, }, - &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "service", - Type: types.ColumnTypeAmbiguous, - }, + { + Name: "service", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, }, } @@ -160,7 +151,7 @@ func TestRangeAggregationPipeline(t *testing.T) { endTs: time.Unix(40, 0), rangeInterval: 10 * time.Second, step: 10 * time.Second, - operation: types.RangeAggregationTypeCount, + operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, } inputA := NewArrowtestPipeline(schema, rowsPipelineA...) @@ -207,7 +198,7 @@ func TestRangeAggregationPipeline(t *testing.T) { endTs: time.Unix(40, 0), rangeInterval: 10 * time.Second, step: 5 * time.Second, - operation: types.RangeAggregationTypeCount, + operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, } inputA := NewArrowtestPipeline(schema, rowsPipelineA...) @@ -268,7 +259,7 @@ func TestRangeAggregationPipeline(t *testing.T) { endTs: time.Unix(40, 0), rangeInterval: 5 * time.Second, step: 10 * time.Second, - operation: types.RangeAggregationTypeCount, + operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, } inputA := NewArrowtestPipeline(schema, rowsPipelineA...) @@ -314,7 +305,7 @@ func TestMatcher(t *testing.T) { endTs: time.Unix(1000, 0), rangeInterval: 1000 * time.Second, // covers time range from 0 - 1000 step: 0, // instant query - operation: types.RangeAggregationTypeCount, + operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, } // Create a single window for instant query @@ -403,7 +394,7 @@ func TestMatcher(t *testing.T) { endTs: time.Unix(300, 0), rangeInterval: 100 * time.Second, step: 100 * time.Second, // step == rangeInterval - operation: types.RangeAggregationTypeCount, + operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, } // Create windows that align with lower/upper bounds and step @@ -472,7 +463,7 @@ func TestMatcher(t *testing.T) { endTs: time.Unix(300, 0), rangeInterval: 80 * time.Second, step: 100 * time.Second, // step > rangeInterval - operation: types.RangeAggregationTypeCount, + operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, } // Create windows that align with lower/upper bounds and step @@ -556,7 +547,7 @@ func TestMatcher(t *testing.T) { endTs: time.Unix(300, 0), rangeInterval: 120 * time.Second, step: 100 * time.Second, // step < rangeInterval - operation: types.RangeAggregationTypeCount, + operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, } // Create windows that align with lower/upper bounds and step diff --git a/pkg/engine/internal/executor/stream_injector.go b/pkg/engine/internal/executor/stream_injector.go index d9afc47923f38..c31896fec6645 100644 --- a/pkg/engine/internal/executor/stream_injector.go +++ b/pkg/engine/internal/executor/stream_injector.go @@ -10,6 +10,7 @@ import ( "github.com/apache/arrow-go/v18/arrow/array" "github.com/apache/arrow-go/v18/arrow/memory" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) @@ -61,7 +62,7 @@ func (si *streamInjector) Inject(ctx context.Context, in arrow.Record) (arrow.Re ) getColumn := func(name string) *labelColumn { - ident := semconv.NewIdentifier(name, types.ColumnTypeLabel, types.Loki.String) + ident := semconv.NewIdentifier(name, physicalpb.COLUMN_TYPE_LABEL, types.Loki.String) if col, ok := labelLookup[ident.FQN()]; ok { return col diff --git a/pkg/engine/internal/executor/topk.go b/pkg/engine/internal/executor/topk.go index dff4683765805..7dca052e562e5 100644 --- a/pkg/engine/internal/executor/topk.go +++ b/pkg/engine/internal/executor/topk.go @@ -7,7 +7,7 @@ import ( "github.com/apache/arrow-go/v18/arrow" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) @@ -17,10 +17,10 @@ type topkOptions struct { Inputs []Pipeline // SortBy is the list of columns to sort by, in order of precedence. - SortBy []physical.ColumnExpression - Ascending bool // Sorts lines in ascending order if true. - NullsFirst bool // When true, considers NULLs < non-NULLs when sorting. - K int // Number of top rows to compute. + SortBy []*physicalpb.ColumnExpression + Ascending bool // Sorts lines in ascending order if true. + NullsFirst bool // When true, considers NULLs < non-NULLs when sorting. + K int64 // Number of top rows to compute. // MaxUnused determines the maximum number of unused rows to retain. An // unused row is any row from a retained record that does not contribute to @@ -55,45 +55,40 @@ func newTopkPipeline(opts topkOptions) (*topkPipeline, error) { Fields: fields, Ascending: opts.Ascending, NullsFirst: opts.NullsFirst, - K: opts.K, + K: int(opts.K), MaxUnused: opts.MaxUnused, }, }, nil } -func exprsToFields(exprs []physical.ColumnExpression) ([]arrow.Field, error) { +func exprsToFields(exprs []*physicalpb.ColumnExpression) ([]arrow.Field, error) { fields := make([]arrow.Field, 0, len(exprs)) for _, expr := range exprs { - expr, ok := expr.(*physical.ColumnExpr) - if !ok { - panic("topkPipeline only supports ColumnExpr expressions") - } - - dt, err := guessLokiType(expr.Ref) + dt, err := guessLokiType(expr) if err != nil { return nil, err } - ident := semconv.NewIdentifier(expr.Ref.Column, expr.Ref.Type, dt) + ident := semconv.NewIdentifier(expr.Name, expr.Type, dt) fields = append(fields, semconv.FieldFromIdent(ident, true)) } return fields, nil } -func guessLokiType(ref types.ColumnRef) (types.DataType, error) { - switch ref.Type { - case types.ColumnTypeBuiltin: - switch ref.Column { +func guessLokiType(expr *physicalpb.ColumnExpression) (types.DataType, error) { + switch expr.Type { + case physicalpb.COLUMN_TYPE_BUILTIN: + switch expr.Name { case types.ColumnNameBuiltinTimestamp: return types.Loki.Timestamp, nil case types.ColumnNameBuiltinMessage: return types.Loki.String, nil default: - panic(fmt.Sprintf("unsupported builtin column type %s", ref)) + panic(fmt.Sprintf("unsupported builtin column type %s", expr)) } - case types.ColumnTypeGenerated: + case physicalpb.COLUMN_TYPE_GENERATED: return types.Loki.Float, nil - case types.ColumnTypeAmbiguous: + case physicalpb.COLUMN_TYPE_AMBIGUOUS: // TODO(rfratto): It's not clear how topk should sort when there's an // ambiguous column reference, since ambiguous column references can // refer to multiple columns. diff --git a/pkg/engine/internal/executor/topk_test.go b/pkg/engine/internal/executor/topk_test.go index d3f6debc8006f..3dbe6b5904216 100644 --- a/pkg/engine/internal/executor/topk_test.go +++ b/pkg/engine/internal/executor/topk_test.go @@ -7,7 +7,7 @@ import ( "github.com/apache/arrow-go/v18/arrow" "github.com/stretchr/testify/require" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/util/arrowtest" @@ -48,9 +48,9 @@ func Test_topk(t *testing.T) { topkPipeline, err := newTopkPipeline(topkOptions{ Inputs: []Pipeline{pipelineA, pipelineB}, - SortBy: []physical.ColumnExpression{ - &physical.ColumnExpr{ - Ref: types.ColumnRef{Column: types.ColumnNameBuiltinTimestamp, Type: types.ColumnTypeBuiltin}, + SortBy: []*physicalpb.ColumnExpression{ + { + Name: types.ColumnNameBuiltinTimestamp, Type: physicalpb.COLUMN_TYPE_BUILTIN, }, }, Ascending: true, @@ -78,9 +78,9 @@ func Test_topk(t *testing.T) { func Test_topk_emptyPipelines(t *testing.T) { topkPipeline, err := newTopkPipeline(topkOptions{ Inputs: []Pipeline{emptyPipeline()}, - SortBy: []physical.ColumnExpression{ - &physical.ColumnExpr{ - Ref: types.ColumnRef{Column: types.ColumnNameBuiltinTimestamp, Type: types.ColumnTypeBuiltin}, + SortBy: []*physicalpb.ColumnExpression{ + { + Name: types.ColumnNameBuiltinTimestamp, Type: physicalpb.COLUMN_TYPE_BUILTIN, }, }, Ascending: true, diff --git a/pkg/engine/internal/executor/util_test.go b/pkg/engine/internal/executor/util_test.go index ecf314fc5fae4..fad408fed05c7 100644 --- a/pkg/engine/internal/executor/util_test.go +++ b/pkg/engine/internal/executor/util_test.go @@ -5,7 +5,6 @@ import ( "errors" "math" "testing" - "time" "github.com/apache/arrow-go/v18/arrow" "github.com/apache/arrow-go/v18/arrow/array" @@ -37,45 +36,6 @@ var ( ) ) -func ascendingTimestampPipeline(start time.Time) *recordGenerator { - return timestampPipeline(start, ascending) -} - -func descendingTimestampPipeline(start time.Time) *recordGenerator { - return timestampPipeline(start, descending) -} - -const ( - ascending = time.Duration(1) - descending = time.Duration(-1) -) - -func timestampPipeline(start time.Time, order time.Duration) *recordGenerator { - return newRecordGenerator( - arrow.NewSchema([]arrow.Field{ - semconv.FieldFromFQN("int64.builtin.id", false), - semconv.FieldFromFQN("timestamp_ns.builtin.timestamp", false), - }, nil), - - func(offset, maxRows, batchSize int64, schema *arrow.Schema) arrow.Record { - idColBuilder := array.NewInt64Builder(memory.DefaultAllocator) - tsColBuilder := array.NewTimestampBuilder(memory.DefaultAllocator, arrow.FixedWidthTypes.Timestamp_ns.(*arrow.TimestampType)) - - rows := int64(0) - for ; rows < batchSize && offset+rows < maxRows; rows++ { - idColBuilder.Append(offset + rows) - tsColBuilder.Append(arrow.Timestamp(start.Add(order * (time.Duration(offset)*time.Second + time.Duration(rows)*time.Millisecond)).UnixNano())) - } - - idData := idColBuilder.NewArray() - tsData := tsColBuilder.NewArray() - - columns := []arrow.Array{idData, tsData} - return array.NewRecord(schema, columns, rows) - }, - ) -} - type batchFunc func(offset, maxRows, batchSize int64, schema *arrow.Schema) arrow.Record type recordGenerator struct { diff --git a/pkg/engine/internal/executor/vector_aggregate.go b/pkg/engine/internal/executor/vector_aggregate.go index 5fcc03a76e833..cb095250d4825 100644 --- a/pkg/engine/internal/executor/vector_aggregate.go +++ b/pkg/engine/internal/executor/vector_aggregate.go @@ -8,7 +8,7 @@ import ( "github.com/apache/arrow-go/v18/arrow" "github.com/apache/arrow-go/v18/arrow/array" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) @@ -22,22 +22,22 @@ type vectorAggregationPipeline struct { aggregator *aggregator evaluator expressionEvaluator - groupBy []physical.ColumnExpression + groupBy []*physicalpb.ColumnExpression tsEval evalFunc // used to evaluate the timestamp column valueEval evalFunc // used to evaluate the value column } var ( - vectorAggregationOperations = map[types.VectorAggregationType]aggregationOperation{ - types.VectorAggregationTypeSum: aggregationOperationSum, - types.VectorAggregationTypeCount: aggregationOperationCount, - types.VectorAggregationTypeMax: aggregationOperationMax, - types.VectorAggregationTypeMin: aggregationOperationMin, + vectorAggregationOperations = map[physicalpb.AggregateVectorOp]aggregationOperation{ + physicalpb.AGGREGATE_VECTOR_OP_SUM: aggregationOperationSum, + physicalpb.AGGREGATE_VECTOR_OP_COUNT: aggregationOperationCount, + physicalpb.AGGREGATE_VECTOR_OP_MAX: aggregationOperationMax, + physicalpb.AGGREGATE_VECTOR_OP_MIN: aggregationOperationMin, } ) -func newVectorAggregationPipeline(inputs []Pipeline, groupBy []physical.ColumnExpression, evaluator expressionEvaluator, operation types.VectorAggregationType) (*vectorAggregationPipeline, error) { +func newVectorAggregationPipeline(inputs []Pipeline, groupBy []*physicalpb.ColumnExpression, evaluator expressionEvaluator, operation physicalpb.AggregateVectorOp) (*vectorAggregationPipeline, error) { if len(inputs) == 0 { return nil, fmt.Errorf("vector aggregation expects at least one input") } @@ -52,18 +52,14 @@ func newVectorAggregationPipeline(inputs []Pipeline, groupBy []physical.ColumnEx evaluator: evaluator, groupBy: groupBy, aggregator: newAggregator(groupBy, 0, op), - tsEval: evaluator.newFunc(&physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: types.ColumnNameBuiltinTimestamp, - Type: types.ColumnTypeBuiltin, - }, - }), - valueEval: evaluator.newFunc(&physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: types.ColumnNameGeneratedValue, - Type: types.ColumnTypeGenerated, - }, - }), + tsEval: evaluator.newFunc(*(&physicalpb.ColumnExpression{ + Name: types.ColumnNameBuiltinTimestamp, + Type: physicalpb.COLUMN_TYPE_BUILTIN, + }).ToExpression()), + valueEval: evaluator.newFunc(*(&physicalpb.ColumnExpression{ + Name: types.ColumnNameGeneratedValue, + Type: physicalpb.COLUMN_TYPE_GENERATED, + }).ToExpression()), }, nil } @@ -114,7 +110,7 @@ func (v *vectorAggregationPipeline) read(ctx context.Context) (arrow.Record, err arrays := make([]*array.String, 0, len(v.groupBy)) for _, columnExpr := range v.groupBy { - vec, err := v.evaluator.eval(columnExpr, record) + vec, err := v.evaluator.eval(*columnExpr.ToExpression(), record) if err != nil { return nil, err } diff --git a/pkg/engine/internal/executor/vector_aggregate_test.go b/pkg/engine/internal/executor/vector_aggregate_test.go index a734f644dc52d..2ff567341978f 100644 --- a/pkg/engine/internal/executor/vector_aggregate_test.go +++ b/pkg/engine/internal/executor/vector_aggregate_test.go @@ -10,9 +10,8 @@ import ( "github.com/apache/arrow-go/v18/arrow/array" "github.com/stretchr/testify/require" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/semconv" - "github.com/grafana/loki/v3/pkg/engine/internal/types" ) func TestVectorAggregationPipeline(t *testing.T) { @@ -67,22 +66,18 @@ func TestVectorAggregationPipeline(t *testing.T) { input2 := NewBufferedPipeline(input2Record) // Create group by expressions - groupBy := []physical.ColumnExpression{ - &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "env", - Type: types.ColumnTypeAmbiguous, - }, + groupBy := []*physicalpb.ColumnExpression{ + { + Name: "env", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, }, - &physical.ColumnExpr{ - Ref: types.ColumnRef{ - Column: "service", - Type: types.ColumnTypeAmbiguous, - }, + { + Name: "service", + Type: physicalpb.COLUMN_TYPE_AMBIGUOUS, }, } - pipeline, err := newVectorAggregationPipeline([]Pipeline{input1, input2}, groupBy, newExpressionEvaluator(), types.VectorAggregationTypeSum) + pipeline, err := newVectorAggregationPipeline([]Pipeline{input1, input2}, groupBy, newExpressionEvaluator(), physicalpb.AGGREGATE_VECTOR_OP_SUM) require.NoError(t, err) defer pipeline.Close() diff --git a/pkg/engine/internal/planner/physical/catalog.go b/pkg/engine/internal/planner/physical/catalog.go index 0023321030706..addd354af51e1 100644 --- a/pkg/engine/internal/planner/physical/catalog.go +++ b/pkg/engine/internal/planner/physical/catalog.go @@ -9,15 +9,15 @@ import ( "github.com/prometheus/prometheus/model/labels" "github.com/grafana/loki/v3/pkg/dataobj/metastore" - "github.com/grafana/loki/v3/pkg/engine/internal/types" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" ) var ( - binOpToMatchTypeMapping = map[types.BinaryOp]labels.MatchType{ - types.BinaryOpEq: labels.MatchEqual, - types.BinaryOpNeq: labels.MatchNotEqual, - types.BinaryOpMatchRe: labels.MatchRegexp, - types.BinaryOpNotMatchRe: labels.MatchNotRegexp, + binOpToMatchTypeMapping = map[physicalpb.BinaryOp]labels.MatchType{ + physicalpb.BINARY_OP_EQ: labels.MatchEqual, + physicalpb.BINARY_OP_NEQ: labels.MatchNotEqual, + physicalpb.BINARY_OP_MATCH_RE: labels.MatchRegexp, + physicalpb.BINARY_OP_NOT_MATCH_RE: labels.MatchNotRegexp, } noShard = ShardInfo{Shard: 0, Of: 1} @@ -64,6 +64,8 @@ func (t *TimeRange) Merge(secondRange TimeRange) TimeRange { return out } +type DataObjLocation string + type FilteredShardDescriptor struct { Location DataObjLocation Streams []int64 @@ -81,8 +83,8 @@ type Catalog interface { // a data object path, a list of stream IDs for // each data object path, a list of sections for // each data object path, and a time range. - ResolveShardDescriptors(Expression, time.Time, time.Time) ([]FilteredShardDescriptor, error) - ResolveShardDescriptorsWithShard(Expression, []Expression, ShardInfo, time.Time, time.Time) ([]FilteredShardDescriptor, error) + ResolveShardDescriptors(physicalpb.Expression, time.Time, time.Time) ([]FilteredShardDescriptor, error) + ResolveShardDescriptorsWithShard(physicalpb.Expression, []*physicalpb.Expression, ShardInfo, time.Time, time.Time) ([]FilteredShardDescriptor, error) } // MetastoreCatalog is the default implementation of [Catalog]. @@ -103,11 +105,11 @@ func NewMetastoreCatalog(ctx context.Context, ms metastore.Metastore) *Metastore // objects based on a given [Expression]. The expression is required // to be a (tree of) [BinaryExpression] with a [ColumnExpression] // on the left and a [LiteralExpression] on the right. -func (c *MetastoreCatalog) ResolveShardDescriptors(selector Expression, from, through time.Time) ([]FilteredShardDescriptor, error) { +func (c *MetastoreCatalog) ResolveShardDescriptors(selector physicalpb.Expression, from, through time.Time) ([]FilteredShardDescriptor, error) { return c.ResolveShardDescriptorsWithShard(selector, nil, noShard, from, through) } -func (c *MetastoreCatalog) ResolveShardDescriptorsWithShard(selector Expression, predicates []Expression, shard ShardInfo, from, through time.Time) ([]FilteredShardDescriptor, error) { +func (c *MetastoreCatalog) ResolveShardDescriptorsWithShard(selector physicalpb.Expression, predicates []*physicalpb.Expression, shard ShardInfo, from, through time.Time) ([]FilteredShardDescriptor, error) { if c.metastore == nil { return nil, errors.New("no metastore to resolve objects") } @@ -116,7 +118,7 @@ func (c *MetastoreCatalog) ResolveShardDescriptorsWithShard(selector Expression, } // resolveShardDescriptorsWithIndex expects the metastore to initially point to index objects, not the log objects directly. -func (c *MetastoreCatalog) resolveShardDescriptorsWithIndex(selector Expression, predicates []Expression, shard ShardInfo, from, through time.Time) ([]FilteredShardDescriptor, error) { +func (c *MetastoreCatalog) resolveShardDescriptorsWithIndex(selector physicalpb.Expression, predicates []*physicalpb.Expression, shard ShardInfo, from, through time.Time) ([]FilteredShardDescriptor, error) { if c.metastore == nil { return nil, errors.New("no metastore to resolve objects") } @@ -128,7 +130,7 @@ func (c *MetastoreCatalog) resolveShardDescriptorsWithIndex(selector Expression, predicateMatchers := make([]*labels.Matcher, 0, len(predicates)) for _, predicate := range predicates { - matchers, err := expressionToMatchers(predicate, true) + matchers, err := expressionToMatchers(*predicate, true) if err != nil { // Not all predicates are supported by the metastore, so some will be skipped continue @@ -173,34 +175,31 @@ func filterDescriptorsForShard(shard ShardInfo, sectionDescriptors []*metastore. // The selector expression is required to be a (tree of) [BinaryExpression] // with a [ColumnExpression] on the left and a [LiteralExpression] on the right. // It optionally supports ambiguous column references. Non-ambiguous column references are label matchers. -func expressionToMatchers(selector Expression, allowAmbiguousColumnRefs bool) ([]*labels.Matcher, error) { - if selector == nil { - return nil, nil - } +func expressionToMatchers(selector physicalpb.Expression, allowAmbiguousColumnRefs bool) ([]*labels.Matcher, error) { - switch expr := selector.(type) { - case *BinaryExpr: - switch expr.Op { - case types.BinaryOpAnd: - lhs, err := expressionToMatchers(expr.Left, allowAmbiguousColumnRefs) + switch expr := selector.Kind.(type) { + case *physicalpb.Expression_BinaryExpression: + switch expr.BinaryExpression.Op { + case physicalpb.BINARY_OP_AND: + lhs, err := expressionToMatchers(*expr.BinaryExpression.Left, allowAmbiguousColumnRefs) if err != nil { return nil, err } - rhs, err := expressionToMatchers(expr.Right, allowAmbiguousColumnRefs) + rhs, err := expressionToMatchers(*expr.BinaryExpression.Right, allowAmbiguousColumnRefs) if err != nil { return nil, err } return append(lhs, rhs...), nil - case types.BinaryOpEq, types.BinaryOpNeq, types.BinaryOpMatchRe, types.BinaryOpNotMatchRe: - op, err := convertBinaryOp(expr.Op) + case physicalpb.BINARY_OP_EQ, physicalpb.BINARY_OP_NEQ, physicalpb.BINARY_OP_MATCH_RE, physicalpb.BINARY_OP_NOT_MATCH_RE: + op, err := convertBinaryOp(expr.BinaryExpression.Op) if err != nil { return nil, err } - name, err := convertColumnRef(expr.Left, allowAmbiguousColumnRefs) + name, err := convertColumnRef(*expr.BinaryExpression.Left, allowAmbiguousColumnRefs) if err != nil { return nil, err } - value, err := convertLiteralToString(expr.Right) + value, err := convertLiteralToString(*expr.BinaryExpression.Right) if err != nil { return nil, err } @@ -210,36 +209,37 @@ func expressionToMatchers(selector Expression, allowAmbiguousColumnRefs bool) ([ } return []*labels.Matcher{lhs}, nil default: - return nil, fmt.Errorf("invalid binary expression in stream selector expression: %v", expr.Op.String()) + return nil, fmt.Errorf("invalid binary expression in stream selector expression: %v", expr.BinaryExpression.Op.String()) } default: return nil, fmt.Errorf("invalid expression type in stream selector expression: %T", expr) } } -func convertLiteralToString(expr Expression) (string, error) { - l, ok := expr.(*LiteralExpr) +func convertLiteralToString(expr physicalpb.Expression) (string, error) { + l, ok := expr.Kind.(*physicalpb.Expression_LiteralExpression) if !ok { return "", fmt.Errorf("expected literal expression, got %T", expr) } - if l.ValueType() != types.Loki.String { - return "", fmt.Errorf("literal type is not a string, got %v", l.ValueType()) + _, ok = l.LiteralExpression.Kind.(*physicalpb.LiteralExpression_StringLiteral) + if !ok { + return "", fmt.Errorf("literal type is not a string, got %v", l.LiteralExpression.Kind) } - return l.Any().(string), nil + return l.LiteralExpression.GetStringLiteral().Value, nil } -func convertColumnRef(expr Expression, allowAmbiguousColumnRefs bool) (string, error) { - ref, ok := expr.(*ColumnExpr) +func convertColumnRef(expr physicalpb.Expression, allowAmbiguousColumnRefs bool) (string, error) { + ref, ok := expr.Kind.(*physicalpb.Expression_ColumnExpression) if !ok { return "", fmt.Errorf("expected column expression, got %T", expr) } - if !allowAmbiguousColumnRefs && ref.Ref.Type != types.ColumnTypeLabel { - return "", fmt.Errorf("column type is not a label, got %v", ref.Ref.Type) + if !allowAmbiguousColumnRefs && ref.ColumnExpression.Type != physicalpb.COLUMN_TYPE_LABEL { + return "", fmt.Errorf("column type is not a label, got %v", ref.ColumnExpression.Type) } - return ref.Ref.Column, nil + return ref.ColumnExpression.Name, nil } -func convertBinaryOp(t types.BinaryOp) (labels.MatchType, error) { +func convertBinaryOp(t physicalpb.BinaryOp) (labels.MatchType, error) { ty, ok := binOpToMatchTypeMapping[t] if !ok { return -1, fmt.Errorf("invalid binary operator for matcher: %v", t) diff --git a/pkg/engine/internal/planner/physical/catalog_test.go b/pkg/engine/internal/planner/physical/catalog_test.go index 9aabcc9bae2fb..7a9ffbc02940c 100644 --- a/pkg/engine/internal/planner/physical/catalog_test.go +++ b/pkg/engine/internal/planner/physical/catalog_test.go @@ -8,45 +8,46 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/loki/v3/pkg/dataobj/metastore" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) func TestCatalog_ConvertLiteral(t *testing.T) { tests := []struct { - expr Expression + expr physicalpb.Expression want string wantErr bool }{ { - expr: NewLiteral("foo"), + expr: *NewLiteral("foo").ToExpression(), want: "foo", }, { - expr: NewLiteral(false), + expr: *NewLiteral(false).ToExpression(), wantErr: true, }, { - expr: NewLiteral(int64(123)), + expr: *NewLiteral(int64(123)).ToExpression(), wantErr: true, }, { - expr: NewLiteral(types.Timestamp(time.Now().UnixNano())), + expr: *NewLiteral(types.Timestamp(time.Now().UnixNano())).ToExpression(), wantErr: true, }, { - expr: NewLiteral(types.Duration(time.Hour.Nanoseconds())), + expr: *NewLiteral(types.Duration(time.Hour.Nanoseconds())).ToExpression(), wantErr: true, }, { - expr: newColumnExpr("foo", types.ColumnTypeLabel), + expr: *newColumnExpr("foo", physicalpb.COLUMN_TYPE_LABEL).ToExpression(), wantErr: true, }, { - expr: &BinaryExpr{ - Left: newColumnExpr("foo", types.ColumnTypeLabel), - Right: NewLiteral("foo"), - Op: types.BinaryOpEq, - }, + expr: *(&physicalpb.BinaryExpression{ + Left: newColumnExpr("foo", physicalpb.COLUMN_TYPE_LABEL).ToExpression(), + Right: NewLiteral("foo").ToExpression(), + Op: physicalpb.BINARY_OP_EQ, + }).ToExpression(), wantErr: true, }, } @@ -66,32 +67,32 @@ func TestCatalog_ConvertLiteral(t *testing.T) { func TestCatalog_ConvertColumnRef(t *testing.T) { tests := []struct { - expr Expression + expr physicalpb.Expression want string wantErr bool }{ { - expr: newColumnExpr("foo", types.ColumnTypeLabel), + expr: *newColumnExpr("foo", physicalpb.COLUMN_TYPE_LABEL).ToExpression(), want: "foo", }, { - expr: newColumnExpr("foo", types.ColumnTypeAmbiguous), + expr: *newColumnExpr("foo", physicalpb.COLUMN_TYPE_AMBIGUOUS).ToExpression(), wantErr: true, }, { - expr: newColumnExpr("foo", types.ColumnTypeBuiltin), + expr: *newColumnExpr("foo", physicalpb.COLUMN_TYPE_BUILTIN).ToExpression(), wantErr: true, }, { - expr: NewLiteral(false), + expr: *NewLiteral(false).ToExpression(), wantErr: true, }, { - expr: &BinaryExpr{ - Left: newColumnExpr("foo", types.ColumnTypeLabel), - Right: NewLiteral("foo"), - Op: types.BinaryOpEq, - }, + expr: *(&physicalpb.BinaryExpression{ + Left: newColumnExpr("foo", physicalpb.COLUMN_TYPE_LABEL).ToExpression(), + Right: NewLiteral("foo").ToExpression(), + Op: physicalpb.BINARY_OP_EQ, + }).ToExpression(), wantErr: true, }, } @@ -111,42 +112,42 @@ func TestCatalog_ConvertColumnRef(t *testing.T) { func TestCatalog_ExpressionToMatchers(t *testing.T) { tests := []struct { - expr Expression + expr physicalpb.Expression want []*labels.Matcher wantErr bool }{ { - expr: newColumnExpr("foo", types.ColumnTypeLabel), + expr: *newColumnExpr("foo", physicalpb.COLUMN_TYPE_LABEL).ToExpression(), wantErr: true, }, { - expr: NewLiteral("foo"), + expr: *NewLiteral("foo").ToExpression(), wantErr: true, }, { - expr: &BinaryExpr{ - Left: newColumnExpr("foo", types.ColumnTypeLabel), - Right: NewLiteral("bar"), - Op: types.BinaryOpEq, - }, + expr: *(&physicalpb.BinaryExpression{ + Left: newColumnExpr("foo", physicalpb.COLUMN_TYPE_LABEL).ToExpression(), + Right: NewLiteral("bar").ToExpression(), + Op: physicalpb.BINARY_OP_EQ, + }).ToExpression(), want: []*labels.Matcher{ labels.MustNewMatcher(labels.MatchEqual, "foo", "bar"), }, }, { - expr: &BinaryExpr{ - Left: &BinaryExpr{ - Left: newColumnExpr("foo", types.ColumnTypeLabel), - Right: NewLiteral("bar"), - Op: types.BinaryOpEq, - }, - Right: &BinaryExpr{ - Left: newColumnExpr("bar", types.ColumnTypeLabel), - Right: NewLiteral("baz"), - Op: types.BinaryOpNeq, - }, - Op: types.BinaryOpAnd, - }, + expr: *(&physicalpb.BinaryExpression{ + Left: (&physicalpb.BinaryExpression{ + Left: newColumnExpr("foo", physicalpb.COLUMN_TYPE_LABEL).ToExpression(), + Right: NewLiteral("bar").ToExpression(), + Op: physicalpb.BINARY_OP_EQ, + }).ToExpression(), + Right: (&physicalpb.BinaryExpression{ + Left: newColumnExpr("bar", physicalpb.COLUMN_TYPE_LABEL).ToExpression(), + Right: NewLiteral("baz").ToExpression(), + Op: physicalpb.BINARY_OP_NEQ, + }).ToExpression(), + Op: physicalpb.BINARY_OP_AND, + }).ToExpression(), want: []*labels.Matcher{ labels.MustNewMatcher(labels.MatchEqual, "foo", "bar"), labels.MustNewMatcher(labels.MatchNotEqual, "bar", "baz"), diff --git a/pkg/engine/internal/planner/physical/compat.go b/pkg/engine/internal/planner/physical/compat.go deleted file mode 100644 index a37468e5592c8..0000000000000 --- a/pkg/engine/internal/planner/physical/compat.go +++ /dev/null @@ -1,49 +0,0 @@ -package physical - -import ( - "fmt" - - "github.com/grafana/loki/v3/pkg/engine/internal/types" -) - -// ColumnCompat represents a compactibilty operation in the physical plan that -// moves a values from a conflicting metadata column with a label column into a new column suffixed with `_extracted`. -type ColumnCompat struct { - id string - - // TODO(chaudum): These fields are poorly named. Come up with more descriptive names. - Source types.ColumnType // column type of the column that may colide with columns of the same name but with collision type - Destination types.ColumnType // column type of the generated _extracted column (should be same as source) - Collision types.ColumnType // column type of the column that a source type column may collide with -} - -// ID implements the [Node] interface. -// Returns a string that uniquely identifies the node in the plan. -func (m *ColumnCompat) ID() string { - if m.id == "" { - return fmt.Sprintf("%p", m) - } - - return m.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (m *ColumnCompat) Clone() Node { - return &ColumnCompat{ - Source: m.Source, - Destination: m.Destination, - Collision: m.Collision, - } -} - -// Type implements the [Node] interface. -// Returns the type of the node. -func (m *ColumnCompat) Type() NodeType { - return NodeTypeCompat -} - -// Accept implements the [Node] interface. -// Dispatches itself to the provided [Visitor] v -func (m *ColumnCompat) Accept(v Visitor) error { - return v.VisitCompat(m) -} diff --git a/pkg/engine/internal/planner/physical/dataobjscan.go b/pkg/engine/internal/planner/physical/dataobjscan.go deleted file mode 100644 index 1c02d691a90c1..0000000000000 --- a/pkg/engine/internal/planner/physical/dataobjscan.go +++ /dev/null @@ -1,66 +0,0 @@ -package physical - -import ( - "fmt" - "slices" -) - -// DataObjLocation is a string that uniquely indentifies a data object location in -// object storage. -type DataObjLocation string - -// DataObjScan represents a physical plan operation for reading data objects. -// It contains information about the object location, stream IDs, projections, -// predicates for reading data from a data object. -type DataObjScan struct { - id string - - // Location is the unique name of the data object that is used as source for - // reading streams. - Location DataObjLocation - // Section is the section index inside the data object to scan. - Section int - // StreamIDs is a set of stream IDs inside the data object. These IDs are - // only unique in the context of a single data object. - StreamIDs []int64 - // Projections are used to limit the columns that are read to the ones - // provided in the column expressions to reduce the amount of data that needs - // to be processed. - Projections []ColumnExpression - // Predicates are used to filter rows to reduce the amount of rows that are - // returned. Predicates would almost always contain a time range filter to - // only read the logs for the requested time range. - Predicates []Expression -} - -// ID implements the [Node] interface. -// Returns a string that uniquely identifies the node in the plan. -func (s *DataObjScan) ID() string { - if s.id == "" { - return fmt.Sprintf("%p", s) - } - return s.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (s *DataObjScan) Clone() Node { - return &DataObjScan{ - Location: s.Location, - Section: s.Section, - StreamIDs: slices.Clone(s.StreamIDs), - Projections: cloneExpressions(s.Projections), - Predicates: cloneExpressions(s.Predicates), - } -} - -// Type implements the [Node] interface. -// Returns the type of the node. -func (*DataObjScan) Type() NodeType { - return NodeTypeDataObjScan -} - -// Accept implements the [Node] interface. -// Dispatches itself to the provided [Visitor] v -func (s *DataObjScan) Accept(v Visitor) error { - return v.VisitDataObjScan(s) -} diff --git a/pkg/engine/internal/planner/physical/expressions.go b/pkg/engine/internal/planner/physical/expressions.go index 2a83984965ea4..5c14de224d3f4 100644 --- a/pkg/engine/internal/planner/physical/expressions.go +++ b/pkg/engine/internal/planner/physical/expressions.go @@ -3,202 +3,41 @@ package physical import ( "fmt" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) -// ExpressionType represents the type of expression in the physical plan. -type ExpressionType uint32 - -const ( - _ ExpressionType = iota // zero-value is an invalid type - - ExprTypeUnary - ExprTypeBinary - ExprTypeLiteral - ExprTypeColumn -) - -// String returns the string representation of the [ExpressionType]. -func (t ExpressionType) String() string { - switch t { - case ExprTypeUnary: - return "UnaryExpression" - case ExprTypeBinary: - return "BinaryExpression" - case ExprTypeLiteral: - return "LiteralExpression" - case ExprTypeColumn: - return "ColumnExpression" - default: - panic(fmt.Sprintf("unknown expression type %d", t)) - } -} - -// Expression is the common interface for all expressions in a physical plan. -type Expression interface { - fmt.Stringer - Clone() Expression - Type() ExpressionType - isExpr() -} - -func cloneExpressions[E Expression](exprs []E) []E { - clonedExprs := make([]E, len(exprs)) - for i, expr := range exprs { - clonedExprs[i] = expr.Clone().(E) - } - return clonedExprs -} - -// UnaryExpression is the common interface for all unary expressions in a -// physical plan. -type UnaryExpression interface { - Expression - isUnaryExpr() -} - -// BinaryExpression is the common interface for all binary expressions in a -// physical plan. -type BinaryExpression interface { - Expression - isBinaryExpr() -} - -// LiteralExpression is the common interface for all literal expressions in a -// physical plan. -type LiteralExpression interface { - Expression - ValueType() types.DataType - isLiteralExpr() -} - -// ColumnExpression is the common interface for all column expressions in a -// physical plan. -type ColumnExpression interface { - Expression - isColumnExpr() -} - -// UnaryExpr is an expression that implements the [UnaryExpression] interface. -type UnaryExpr struct { - // Left is the expression being operated on - Left Expression - // Op is the unary operator to apply to the expression - Op types.UnaryOp -} - -func (*UnaryExpr) isExpr() {} -func (*UnaryExpr) isUnaryExpr() {} - -// Clone returns a copy of the [UnaryExpr]. -func (e *UnaryExpr) Clone() Expression { - return &UnaryExpr{ - Left: e.Left.Clone(), - Op: e.Op, - } -} - -func (e *UnaryExpr) String() string { - return fmt.Sprintf("%s(%s)", e.Op, e.Left) -} - -// ID returns the type of the [UnaryExpr]. -func (*UnaryExpr) Type() ExpressionType { - return ExprTypeUnary -} - -// BinaryExpr is an expression that implements the [BinaryExpression] interface. -type BinaryExpr struct { - Left, Right Expression - Op types.BinaryOp -} - -func (*BinaryExpr) isExpr() {} -func (*BinaryExpr) isBinaryExpr() {} - -// Clone returns a copy of the [BinaryExpr]. -func (e *BinaryExpr) Clone() Expression { - return &BinaryExpr{ - Left: e.Left.Clone(), - Right: e.Right.Clone(), - Op: e.Op, - } -} - -func (e *BinaryExpr) String() string { - return fmt.Sprintf("%s(%s, %s)", e.Op, e.Left, e.Right) -} - -// ID returns the type of the [BinaryExpr]. -func (*BinaryExpr) Type() ExpressionType { - return ExprTypeBinary -} - -// LiteralExpr is an expression that implements the [LiteralExpression] interface. -type LiteralExpr struct { - types.Literal -} - -func (*LiteralExpr) isExpr() {} -func (*LiteralExpr) isLiteralExpr() {} - -// Clone returns a copy of the [LiteralExpr]. -func (e *LiteralExpr) Clone() Expression { - // No need to clone literals. - return &LiteralExpr{Literal: e.Literal} -} - -// String returns the string representation of the literal value. -func (e *LiteralExpr) String() string { - return e.Literal.String() -} - -// ID returns the type of the [LiteralExpr]. -func (*LiteralExpr) Type() ExpressionType { - return ExprTypeLiteral -} - -// ValueType returns the kind of value represented by the literal. -func (e *LiteralExpr) ValueType() types.DataType { - return e.Literal.Type() -} - -func NewLiteral(value types.LiteralType) *LiteralExpr { +func NewLiteral(value types.LiteralType) *physicalpb.LiteralExpression { if value == nil { - return &LiteralExpr{Literal: types.NewNullLiteral()} + return &physicalpb.LiteralExpression{Kind: &physicalpb.LiteralExpression_NullLiteral{}} } - return &LiteralExpr{Literal: types.NewLiteral(value)} -} - -// ColumnExpr is an expression that implements the [ColumnExpr] interface. -type ColumnExpr struct { - Ref types.ColumnRef -} - -func newColumnExpr(column string, ty types.ColumnType) *ColumnExpr { - return &ColumnExpr{ - Ref: types.ColumnRef{ - Column: column, - Type: ty, - }, + switch val := any(value).(type) { + case bool: + return &physicalpb.LiteralExpression{Kind: &physicalpb.LiteralExpression_BoolLiteral{BoolLiteral: &physicalpb.BoolLiteral{Value: val}}} + case string: + return &physicalpb.LiteralExpression{Kind: &physicalpb.LiteralExpression_StringLiteral{StringLiteral: &physicalpb.StringLiteral{Value: val}}} + case int64: + return &physicalpb.LiteralExpression{Kind: &physicalpb.LiteralExpression_IntegerLiteral{IntegerLiteral: &physicalpb.IntegerLiteral{Value: val}}} + case float64: + return &physicalpb.LiteralExpression{Kind: &physicalpb.LiteralExpression_FloatLiteral{FloatLiteral: &physicalpb.FloatLiteral{Value: val}}} + case types.Timestamp: + return &physicalpb.LiteralExpression{Kind: &physicalpb.LiteralExpression_TimestampLiteral{TimestampLiteral: &physicalpb.TimestampLiteral{Value: int64(val)}}} + case types.Duration: + return &physicalpb.LiteralExpression{Kind: &physicalpb.LiteralExpression_DurationLiteral{DurationLiteral: &physicalpb.DurationLiteral{Value: int64(val)}}} + case types.Bytes: + return &physicalpb.LiteralExpression{Kind: &physicalpb.LiteralExpression_BytesLiteral{BytesLiteral: &physicalpb.BytesLiteral{Value: int64(val)}}} + default: + panic(fmt.Sprintf("invalid literal value type %T", value)) } } -func (e *ColumnExpr) isExpr() {} -func (e *ColumnExpr) isColumnExpr() {} - -// Clone returns a copy of the [ColumnExpr]. -func (e *ColumnExpr) Clone() Expression { - return &ColumnExpr{Ref: e.Ref} -} - -// String returns the string representation of the column expression. -// It contains of the name of the column and its type, joined by a dot (`.`). -func (e *ColumnExpr) String() string { - return e.Ref.String() +func newColumnExpr(column string, ty physicalpb.ColumnType) *physicalpb.ColumnExpression { + return &physicalpb.ColumnExpression{ + Name: column, + Type: ty, + } } -// ID returns the type of the [ColumnExpr]. -func (e *ColumnExpr) Type() ExpressionType { - return ExprTypeColumn +func newBinaryExpr(left *physicalpb.Expression, right *physicalpb.Expression, op physicalpb.BinaryOp) *physicalpb.BinaryExpression { + return &physicalpb.BinaryExpression{Left: left, Right: right, Op: op} } diff --git a/pkg/engine/internal/planner/physical/expressions_test.go b/pkg/engine/internal/planner/physical/expressions_test.go deleted file mode 100644 index 952237b683e2d..0000000000000 --- a/pkg/engine/internal/planner/physical/expressions_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package physical - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/grafana/loki/v3/pkg/engine/internal/types" -) - -func TestExpressionTypes(t *testing.T) { - tests := []struct { - name string - expr Expression - expected ExpressionType - }{ - { - name: "UnaryExpression", - expr: &UnaryExpr{ - Op: types.UnaryOpNot, - Left: NewLiteral(true), - }, - expected: ExprTypeUnary, - }, - { - name: "BinaryExpression", - expr: &BinaryExpr{ - Op: types.BinaryOpEq, - Left: &ColumnExpr{Ref: types.ColumnRef{Column: "col", Type: types.ColumnTypeBuiltin}}, - Right: NewLiteral("foo"), - }, - expected: ExprTypeBinary, - }, - { - name: "LiteralExpression", - expr: NewLiteral("col"), - expected: ExprTypeLiteral, - }, - { - name: "ColumnExpression", - expr: &ColumnExpr{Ref: types.ColumnRef{Column: "col", Type: types.ColumnTypeBuiltin}}, - expected: ExprTypeColumn, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require.Equal(t, tt.expected, tt.expr.Type()) - require.Equal(t, tt.name, tt.expr.Type().String()) - }) - } -} - -func TestLiteralExpr(t *testing.T) { - t.Run("boolean", func(t *testing.T) { - var expr Expression = NewLiteral(true) - require.Equal(t, ExprTypeLiteral, expr.Type()) - literal, ok := expr.(LiteralExpression) - require.True(t, ok) - require.Equal(t, types.Loki.Bool, literal.ValueType()) - }) - - t.Run("float", func(t *testing.T) { - var expr Expression = NewLiteral(123.456789) - require.Equal(t, ExprTypeLiteral, expr.Type()) - literal, ok := expr.(LiteralExpression) - require.True(t, ok) - require.Equal(t, types.Loki.Float, literal.ValueType()) - }) - - t.Run("integer", func(t *testing.T) { - var expr Expression = NewLiteral(int64(123456789)) - require.Equal(t, ExprTypeLiteral, expr.Type()) - literal, ok := expr.(LiteralExpression) - require.True(t, ok) - require.Equal(t, types.Loki.Integer, literal.ValueType()) - }) - - t.Run("timestamp", func(t *testing.T) { - var expr Expression = NewLiteral(types.Timestamp(1741882435000000000)) - require.Equal(t, ExprTypeLiteral, expr.Type()) - literal, ok := expr.(LiteralExpression) - require.True(t, ok) - require.Equal(t, types.Loki.Timestamp, literal.ValueType()) - }) - - t.Run("duration", func(t *testing.T) { - var expr Expression = NewLiteral(types.Duration(3600)) - require.Equal(t, ExprTypeLiteral, expr.Type()) - literal, ok := expr.(LiteralExpression) - require.True(t, ok) - require.Equal(t, types.Loki.Duration, literal.ValueType()) - }) - - t.Run("bytes", func(t *testing.T) { - var expr Expression = NewLiteral(types.Bytes(1024)) - require.Equal(t, ExprTypeLiteral, expr.Type()) - literal, ok := expr.(LiteralExpression) - require.True(t, ok) - require.Equal(t, types.Loki.Bytes, literal.ValueType()) - }) - - t.Run("string", func(t *testing.T) { - var expr Expression = NewLiteral("loki") - require.Equal(t, ExprTypeLiteral, expr.Type()) - literal, ok := expr.(LiteralExpression) - require.True(t, ok) - require.Equal(t, types.Loki.String, literal.ValueType()) - }) -} diff --git a/pkg/engine/internal/planner/physical/filter.go b/pkg/engine/internal/planner/physical/filter.go deleted file mode 100644 index 04cf5a5e84360..0000000000000 --- a/pkg/engine/internal/planner/physical/filter.go +++ /dev/null @@ -1,44 +0,0 @@ -package physical - -import "fmt" - -// Filter represents a filtering operation in the physical plan. -// It contains a list of predicates (conditional expressions) that are later -// evaluated against the input columns and produce a result that only contains -// rows that match the given conditions. The list of expressions are chained -// with a logical AND. -type Filter struct { - id string - - // Predicates is a list of filter expressions that are used to discard not - // matching rows during execution. - Predicates []Expression -} - -// ID implements the [Node] interface. -// Returns a string that uniquely identifies the node in the plan. -func (f *Filter) ID() string { - if f.id == "" { - return fmt.Sprintf("%p", f) - } - return f.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (f *Filter) Clone() Node { - return &Filter{ - Predicates: cloneExpressions(f.Predicates), - } -} - -// Type implements the [Node] interface. -// Returns the type of the node. -func (*Filter) Type() NodeType { - return NodeTypeFilter -} - -// Accept implements the [Node] interface. -// Dispatches itself to the provided [Visitor] v -func (f *Filter) Accept(v Visitor) error { - return v.VisitFilter(f) -} diff --git a/pkg/engine/internal/planner/physical/join.go b/pkg/engine/internal/planner/physical/join.go deleted file mode 100644 index 489259ba51cc1..0000000000000 --- a/pkg/engine/internal/planner/physical/join.go +++ /dev/null @@ -1,35 +0,0 @@ -package physical - -import "fmt" - -// Join represents a join operation in the physical plan. -// For now it is only an inner join on `timestamp`. Will be expanded later. -type Join struct { - id string -} - -// ID implements the [Node] interface. -// Returns a string that uniquely identifies the node in the plan. -func (f *Join) ID() string { - if f.id == "" { - return fmt.Sprintf("%p", f) - } - return f.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (f *Join) Clone() Node { - return &Join{} -} - -// Type implements the [Node] interface. -// Returns the type of the node. -func (*Join) Type() NodeType { - return NodeTypeJoin -} - -// Accept implements the [Node] interface. -// Dispatches itself to the provided [Visitor] v -func (f *Join) Accept(v Visitor) error { - return v.VisitJoin(f) -} diff --git a/pkg/engine/internal/planner/physical/limit.go b/pkg/engine/internal/planner/physical/limit.go deleted file mode 100644 index 46811d15640f8..0000000000000 --- a/pkg/engine/internal/planner/physical/limit.go +++ /dev/null @@ -1,45 +0,0 @@ -package physical - -import "fmt" - -// Limit represents a limiting operation in the physical plan that applies -// offset and limit to the result set. The offset specifies how many rows to -// skip before starting to return results, while limit specifies the maximum -// number of rows to return. -type Limit struct { - id string - - // Skip specifies how many initial rows should be skipped. - Skip uint32 - // Fetch specifies how many rows should be returned in total. - Fetch uint32 -} - -// ID implements the [Node] interface. -// Returns a string that uniquely identifies the node in the plan. -func (l *Limit) ID() string { - if l.id == "" { - return fmt.Sprintf("%p", l) - } - return l.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (l *Limit) Clone() Node { - return &Limit{ - Skip: l.Skip, - Fetch: l.Fetch, - } -} - -// Type implements the [Node] interface. -// Returns the type of the node. -func (*Limit) Type() NodeType { - return NodeTypeLimit -} - -// Accept implements the [Node] interface. -// Dispatches itself to the provided [Visitor] v -func (l *Limit) Accept(v Visitor) error { - return v.VisitLimit(l) -} diff --git a/pkg/engine/internal/planner/physical/optimizer.go b/pkg/engine/internal/planner/physical/optimizer.go index bf71a6288ddc3..a32ed2fa0e2f5 100644 --- a/pkg/engine/internal/planner/physical/optimizer.go +++ b/pkg/engine/internal/planner/physical/optimizer.go @@ -5,37 +5,37 @@ import ( "slices" "sort" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" - "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" ) // A rule is a transformation that can be applied on a Node. type rule interface { // apply tries to apply the transformation on the node. // It returns a boolean indicating whether the transformation has been applied. - apply(Node) bool + apply(physicalpb.Node) bool } var _ rule = (*removeNoopFilter)(nil) // removeNoopFilter is a rule that removes Filter nodes without predicates. type removeNoopFilter struct { - plan *Plan + plan *physicalpb.Plan } // apply implements rule. -func (r *removeNoopFilter) apply(root Node) bool { +func (r *removeNoopFilter) apply(root physicalpb.Node) bool { // collect filter nodes. - nodes := findMatchingNodes(r.plan, root, func(node Node) bool { - _, ok := node.(*Filter) + nodes := findMatchingNodes(r.plan, root, func(node physicalpb.Node) bool { + _, ok := node.(*physicalpb.Filter) return ok }) changed := false for _, n := range nodes { - filter := n.(*Filter) + filter := n.(*physicalpb.Filter) if len(filter.Predicates) == 0 { - r.plan.graph.Eliminate(filter) + r.plan.Eliminate(filter) changed = true } } @@ -47,26 +47,26 @@ var _ rule = (*predicatePushdown)(nil) // predicatePushdown is a rule that moves down filter predicates to the scan nodes. type predicatePushdown struct { - plan *Plan + plan *physicalpb.Plan } // apply implements rule. -func (r *predicatePushdown) apply(root Node) bool { +func (r *predicatePushdown) apply(root physicalpb.Node) bool { // collect filter nodes. - nodes := findMatchingNodes(r.plan, root, func(node Node) bool { - _, ok := node.(*Filter) + nodes := findMatchingNodes(r.plan, root, func(node physicalpb.Node) bool { + _, ok := node.(*physicalpb.Filter) return ok }) changed := false for _, n := range nodes { - filter := n.(*Filter) + filter := n.(*physicalpb.Filter) for i := 0; i < len(filter.Predicates); i++ { - if !canApplyPredicate(filter.Predicates[i]) { + if !canApplyPredicate(*filter.Predicates[i]) { continue } - if ok := r.applyToTargets(filter, filter.Predicates[i]); ok { + if ok := r.applyToTargets(filter, *filter.Predicates[i]); ok { changed = true // remove predicates that have been pushed down filter.Predicates = slices.Delete(filter.Predicates, i, i+1) @@ -78,13 +78,13 @@ func (r *predicatePushdown) apply(root Node) bool { return changed } -func (r *predicatePushdown) applyToTargets(node Node, predicate Expression) bool { +func (r *predicatePushdown) applyToTargets(node physicalpb.Node, predicate physicalpb.Expression) bool { switch node := node.(type) { - case *ScanSet: - node.Predicates = append(node.Predicates, predicate) + case *physicalpb.ScanSet: + node.Predicates = append(node.Predicates, &predicate) return true - case *DataObjScan: - node.Predicates = append(node.Predicates, predicate) + case *physicalpb.DataObjScan: + node.Predicates = append(node.Predicates, &predicate) return true } @@ -97,13 +97,13 @@ func (r *predicatePushdown) applyToTargets(node Node, predicate Expression) bool return changed } -func canApplyPredicate(predicate Expression) bool { - switch pred := predicate.(type) { - case *BinaryExpr: - return canApplyPredicate(pred.Left) && canApplyPredicate(pred.Right) - case *ColumnExpr: - return pred.Ref.Type == types.ColumnTypeBuiltin || pred.Ref.Type == types.ColumnTypeMetadata - case *LiteralExpr: +func canApplyPredicate(predicate physicalpb.Expression) bool { + switch pr := predicate.Kind.(type) { + case *physicalpb.Expression_BinaryExpression: + return canApplyPredicate(*pr.BinaryExpression.Left) && canApplyPredicate(*pr.BinaryExpression.Right) + case *physicalpb.Expression_ColumnExpression: + return (pr.ColumnExpression.Type == physicalpb.COLUMN_TYPE_BUILTIN) || (pr.ColumnExpression.Type == physicalpb.COLUMN_TYPE_METADATA) + case *physicalpb.Expression_LiteralExpression: return true default: return false @@ -114,21 +114,21 @@ var _ rule = (*limitPushdown)(nil) // limitPushdown is a rule that moves down the limit to the scan nodes. type limitPushdown struct { - plan *Plan + plan *physicalpb.Plan } // apply implements rule. -func (r *limitPushdown) apply(root Node) bool { +func (r *limitPushdown) apply(root physicalpb.Node) bool { // collect limit nodes. - nodes := findMatchingNodes(r.plan, root, func(node Node) bool { - _, ok := node.(*Limit) + nodes := findMatchingNodes(r.plan, root, func(node physicalpb.Node) bool { + _, ok := node.(*physicalpb.Limit) return ok }) // propagate limit to target child nodes. changed := false for _, n := range nodes { - limit := n.(*Limit) + limit := n.(*physicalpb.Limit) if r.applyToTargets(limit, limit.Fetch) { changed = true } @@ -137,13 +137,14 @@ func (r *limitPushdown) apply(root Node) bool { } // applyToTargets applies limit on target nodes. -func (r *limitPushdown) applyToTargets(node Node, limit uint32) bool { +func (r *limitPushdown) applyToTargets(node physicalpb.Node, limit uint32) bool { var changed bool - switch node := node.(type) { - case *TopK: - node.K = max(node.K, int(limit)) + n := node.ToPlanNode() + switch node.Kind() { + case physicalpb.NodeKindTopK: + n.GetTopK().K = max(n.GetTopK().K, int64(limit)) changed = true - case *Filter: + case physicalpb.NodeKindFilter: // If there is a filter, child nodes may need to read up to all their lines // to successfully apply the filter, so stop applying limit pushdown. return false @@ -162,18 +163,18 @@ var _ rule = (*groupByPushdown)(nil) // groupByPushdown is an optimisation rule that enables groupby labels to be pushed down to range aggregations. type groupByPushdown struct { - plan *Plan + plan *physicalpb.Plan } -func (r *groupByPushdown) apply(root Node) bool { - nodes := findMatchingNodes(r.plan, root, func(n Node) bool { - _, ok := n.(*VectorAggregation) +func (r *groupByPushdown) apply(root physicalpb.Node) bool { + nodes := findMatchingNodes(r.plan, root, func(n physicalpb.Node) bool { + _, ok := n.(*physicalpb.AggregateVector) return ok }) var changed bool for _, n := range nodes { - vecAgg := n.(*VectorAggregation) + vecAgg := n.(*physicalpb.AggregateVector) if len(vecAgg.GroupBy) == 0 { continue } @@ -182,14 +183,14 @@ func (r *groupByPushdown) apply(root Node) bool { // SUM -> SUM, COUNT // MAX -> MAX // MIN -> MIN - var supportedAggTypes []types.RangeAggregationType + var supportedAggTypes []physicalpb.AggregateRangeOp switch vecAgg.Operation { - case types.VectorAggregationTypeSum: - supportedAggTypes = append(supportedAggTypes, types.RangeAggregationTypeSum, types.RangeAggregationTypeCount) - case types.VectorAggregationTypeMax: - supportedAggTypes = append(supportedAggTypes, types.RangeAggregationTypeMax) - case types.VectorAggregationTypeMin: - supportedAggTypes = append(supportedAggTypes, types.RangeAggregationTypeMin) + case physicalpb.AGGREGATE_VECTOR_OP_SUM: + supportedAggTypes = append(supportedAggTypes, physicalpb.AGGREGATE_RANGE_OP_SUM, physicalpb.AGGREGATE_RANGE_OP_COUNT) + case physicalpb.AGGREGATE_VECTOR_OP_MAX: + supportedAggTypes = append(supportedAggTypes, physicalpb.AGGREGATE_RANGE_OP_MAX) + case physicalpb.AGGREGATE_VECTOR_OP_MIN: + supportedAggTypes = append(supportedAggTypes, physicalpb.AGGREGATE_RANGE_OP_MIN) default: return false } @@ -202,22 +203,17 @@ func (r *groupByPushdown) apply(root Node) bool { return changed } -func (r *groupByPushdown) applyToTargets(node Node, groupBy []ColumnExpression, supportedAggTypes ...types.RangeAggregationType) bool { +func (r *groupByPushdown) applyToTargets(node physicalpb.Node, groupBy []*physicalpb.ColumnExpression, supportedAggTypes ...physicalpb.AggregateRangeOp) bool { var changed bool - switch node := node.(type) { - case *RangeAggregation: - if !slices.Contains(supportedAggTypes, node.Operation) { + switch node := node.ToPlanNode().Kind.(type) { + case *physicalpb.PlanNode_AggregateRange: + if !slices.Contains(supportedAggTypes, node.AggregateRange.Operation) { return false } for _, colExpr := range groupBy { - colExpr, ok := colExpr.(*ColumnExpr) - if !ok { - continue - } - var wasAdded bool - node.PartitionBy, wasAdded = addUniqueColumnExpr(node.PartitionBy, colExpr) + node.AggregateRange.PartitionBy, wasAdded = addUniqueColumnExpr(node.AggregateRange.PartitionBy, colExpr) if wasAdded { changed = true } @@ -240,11 +236,11 @@ var _ rule = (*projectionPushdown)(nil) // projectionPushdown is a rule that pushes down column projections. type projectionPushdown struct { - plan *Plan + plan *physicalpb.Plan } // apply implements rule. -func (r *projectionPushdown) apply(node Node) bool { +func (r *projectionPushdown) apply(node physicalpb.Node) bool { if !r.isMetricQuery() { return false } @@ -254,21 +250,21 @@ func (r *projectionPushdown) apply(node Node) bool { // propagateProjections propagates projections down the plan tree. // It collects required columns from source nodes (consumers) and pushes them down to target nodes (scanners). -func (r *projectionPushdown) propagateProjections(node Node, projections []ColumnExpression) bool { +func (r *projectionPushdown) propagateProjections(node physicalpb.Node, projections []*physicalpb.ColumnExpression) bool { var changed bool switch node := node.(type) { - case *RangeAggregation: - // [Source] RangeAggregation requires partitionBy columns & timestamp. + case *physicalpb.AggregateRange: + // [Source] AggregateRange requires partitionBy columns & timestamp. projections = append(projections, node.PartitionBy...) // Always project timestamp column even if partitionBy is empty. // Timestamp values are required to perform range aggregation. - projections = append(projections, &ColumnExpr{Ref: types.ColumnRef{Column: types.ColumnNameBuiltinTimestamp, Type: types.ColumnTypeBuiltin}}) - case *Filter: + projections = append(projections, &physicalpb.ColumnExpression{Name: types.ColumnNameBuiltinTimestamp, Type: physicalpb.COLUMN_TYPE_BUILTIN}) + case *physicalpb.Filter: // [Source] Filter nodes require predicate columns. extracted := extractColumnsFromPredicates(node.Predicates) projections = append(projections, extracted...) - case *ParseNode: + case *physicalpb.Parse: // ParseNode is a special case. It is both a target for projections and a source of projections. // [Target] Ambiguous columns are applied as requested keys to ParseNode. // [Source] Appends builtin message column. @@ -278,21 +274,23 @@ func (r *projectionPushdown) propagateProjections(node Node, projections []Colum changed = true } - case *ScanSet: + case *physicalpb.ScanSet: // [Target] ScanSet - projections are applied here. return r.handleScanSet(node, projections) - case *DataObjScan: + case *physicalpb.DataObjScan: // [Target] DataObjScan - projections are applied here. return r.handleDataobjScan(node, projections) - case *Projection: + case *physicalpb.Projection: if node.Expand { // [Source] column referred by unwrap. for _, e := range node.Expressions { - e, isUnary := e.(*UnaryExpr) - if isUnary && slices.Contains([]types.UnaryOp{types.UnaryOpCastFloat, types.UnaryOpCastBytes, types.UnaryOpCastDuration}, e.Op) { - projections = append(projections, e.Left.(ColumnExpression)) + switch e.Kind.(type) { + case *physicalpb.Expression_UnaryExpression: + if slices.Contains([]physicalpb.UnaryOp{physicalpb.UNARY_OP_CAST_FLOAT, physicalpb.UNARY_OP_CAST_BYTES, physicalpb.UNARY_OP_CAST_DURATION}, e.GetUnaryExpression().Op) { + projections = append(projections, e.GetUnaryExpression().Value.GetColumnExpression()) + } } } } @@ -301,7 +299,7 @@ func (r *projectionPushdown) propagateProjections(node Node, projections []Colum } // dedupe after updating projection list - deduplicateColumns(projections) + projections = deduplicateColumns(projections) // Continue to children for _, child := range r.plan.Children(node) { @@ -314,7 +312,7 @@ func (r *projectionPushdown) propagateProjections(node Node, projections []Colum } // handleScanSet handles projection pushdown for ScanSet nodes -func (r *projectionPushdown) handleScanSet(node *ScanSet, projections []ColumnExpression) bool { +func (r *projectionPushdown) handleScanSet(node *physicalpb.ScanSet, projections []*physicalpb.ColumnExpression) bool { if len(projections) == 0 { return false } @@ -322,11 +320,6 @@ func (r *projectionPushdown) handleScanSet(node *ScanSet, projections []ColumnEx // Add to scan projections if not already present changed := false for _, colExpr := range projections { - colExpr, ok := colExpr.(*ColumnExpr) - if !ok { - continue - } - var wasAdded bool node.Projections, wasAdded = addUniqueColumnExpr(node.Projections, colExpr) if wasAdded { @@ -343,7 +336,7 @@ func (r *projectionPushdown) handleScanSet(node *ScanSet, projections []ColumnEx } // handleDataobjScan handles projection pushdown for DataObjScan nodes -func (r *projectionPushdown) handleDataobjScan(node *DataObjScan, projections []ColumnExpression) bool { +func (r *projectionPushdown) handleDataobjScan(node *physicalpb.DataObjScan, projections []*physicalpb.ColumnExpression) bool { if len(projections) == 0 { return false } @@ -351,11 +344,6 @@ func (r *projectionPushdown) handleDataobjScan(node *DataObjScan, projections [] // Add to scan projections if not already present changed := false for _, colExpr := range projections { - colExpr, ok := colExpr.(*ColumnExpr) - if !ok { - continue - } - var wasAdded bool node.Projections, wasAdded = addUniqueColumnExpr(node.Projections, colExpr) if wasAdded { @@ -372,7 +360,7 @@ func (r *projectionPushdown) handleDataobjScan(node *DataObjScan, projections [] } // handleParseNode handles projection pushdown for ParseNode nodes -func (r *projectionPushdown) handleParseNode(node *ParseNode, projections []ColumnExpression) (bool, []ColumnExpression) { +func (r *projectionPushdown) handleParseNode(node *physicalpb.Parse, projections []*physicalpb.ColumnExpression) (bool, []*physicalpb.ColumnExpression) { _, ambiguousProjections := disambiguateColumns(projections) // Found a ParseNode - update its keys @@ -382,14 +370,9 @@ func (r *projectionPushdown) handleParseNode(node *ParseNode, projections []Colu } for _, p := range ambiguousProjections { - colExpr, ok := p.(*ColumnExpr) - if !ok { - continue - } - // Only collect ambiguous columns to push to parse nodes - if !requestedKeys[colExpr.Ref.Column] { - requestedKeys[colExpr.Ref.Column] = true + if !requestedKeys[p.Name] { + requestedKeys[p.Name] = true } } @@ -401,25 +384,18 @@ func (r *projectionPushdown) handleParseNode(node *ParseNode, projections []Colu node.RequestedKeys = newKeys } - projections = append(projections, &ColumnExpr{ - Ref: types.ColumnRef{Column: types.ColumnNameBuiltinMessage, Type: types.ColumnTypeBuiltin}, + projections = append(projections, &physicalpb.ColumnExpression{ + Name: types.ColumnNameBuiltinMessage, Type: physicalpb.COLUMN_TYPE_BUILTIN, }) return changed, projections } -func sortProjections(a, b ColumnExpression) int { - exprA, aOk := a.(*ColumnExpr) - exprB, bOk := b.(*ColumnExpr) - if !aOk || !bOk { - return 0 - } - - if exprA.Ref.Column < exprB.Ref.Column { +func sortProjections(a, b *physicalpb.ColumnExpression) int { + if a.Name < b.Name { return -1 } - - if exprA.Ref.Column > exprB.Ref.Column { + if a.Name > b.Name { return 1 } @@ -428,11 +404,9 @@ func sortProjections(a, b ColumnExpression) int { // isMetricQuery checks if the plan contains a RangeAggregation or VectorAggregation node, indicating a metric query func (r *projectionPushdown) isMetricQuery() bool { - for node := range r.plan.graph.Nodes() { - if _, ok := node.(*RangeAggregation); ok { - return true - } - if _, ok := node.(*VectorAggregation); ok { + for _, node := range r.plan.Nodes { + switch node.Kind.(type) { + case *physicalpb.PlanNode_AggregateRange, *physicalpb.PlanNode_AggregateVector: return true } } @@ -442,19 +416,19 @@ func (r *projectionPushdown) isMetricQuery() bool { // parallelPushdown is a rule that moves or splits supported operations as a // child of [Parallelize] to parallelize as much work as possible. type parallelPushdown struct { - plan *Plan - pushed map[Node]struct{} + plan *physicalpb.Plan + pushed map[physicalpb.Node]struct{} } var _ rule = (*parallelPushdown)(nil) -func (p *parallelPushdown) apply(root Node) bool { +func (p *parallelPushdown) apply(root physicalpb.Node) bool { if p.pushed == nil { - p.pushed = make(map[Node]struct{}) + p.pushed = make(map[physicalpb.Node]struct{}) } // find all nodes that can be parallelized - nodes := findMatchingNodes(p.plan, root, func(node Node) bool { + nodes := findMatchingNodes(p.plan, root, func(node physicalpb.Node) bool { if _, ok := p.pushed[node]; ok { return false } @@ -474,7 +448,7 @@ func (p *parallelPushdown) apply(root Node) bool { return changed } -func (p *parallelPushdown) applyParallelization(node Node) bool { +func (p *parallelPushdown) applyParallelization(node physicalpb.Node) bool { // There are two catchall cases here: // // 1. Nodes which get *shifted* down into a parallel pushdown, where the @@ -491,19 +465,19 @@ func (p *parallelPushdown) applyParallelization(node Node) bool { // There can be additional special cases, such as parallelizing an `avg` by // pushing down a `sum` and `count` into the Parallelize. switch node.(type) { - case *Projection, *Filter, *ParseNode, *ColumnCompat: // Catchall for shifting nodes + case *physicalpb.Projection, *physicalpb.Filter, *physicalpb.Parse, *physicalpb.ColumnCompat: // Catchall for shifting nodes for _, parallelize := range p.plan.Children(node) { - p.plan.graph.Inject(parallelize, node.Clone()) + p.plan.Inject(parallelize, node.CloneWithNewID()) } - p.plan.graph.Eliminate(node) + p.plan.Eliminate(node) p.pushed[node] = struct{}{} return true - case *TopK: // Catchall for sharding nodes + case *physicalpb.TopK: // Catchall for sharding nodes // TODO: Add Range aggregation as a sharding node for _, parallelize := range p.plan.Children(node) { - p.plan.graph.Inject(parallelize, node.Clone()) + p.plan.Inject(parallelize, node.CloneWithNewID()) } p.pushed[node] = struct{}{} return true @@ -514,7 +488,7 @@ func (p *parallelPushdown) applyParallelization(node Node) bool { // canPushdown returns true if the given node has children that are all of type // [NodeTypeParallelize]. Nodes with no children are not supported. -func (p *parallelPushdown) canPushdown(node Node) bool { +func (p *parallelPushdown) canPushdown(node physicalpb.Node) bool { children := p.plan.Children(node) if len(children) == 0 { // Must have at least one child. @@ -523,20 +497,37 @@ func (p *parallelPushdown) canPushdown(node Node) bool { // foundNonParallelize is true if there is at least one child that is not of // type [NodeTypeParallelize]. - foundNonParallelize := slices.ContainsFunc(children, func(n Node) bool { - return n.Type() != NodeTypeParallelize + foundNonParallelize := slices.ContainsFunc(children, func(n physicalpb.Node) bool { + return n.Kind() != physicalpb.NodeKindParallelize }) return !foundNonParallelize } +// disambiguateColumns splits columns into ambiguous and unambiguous columns +func disambiguateColumns(columns []*physicalpb.ColumnExpression) ([]*physicalpb.ColumnExpression, []*physicalpb.ColumnExpression) { + ambiguousColumns := make([]*physicalpb.ColumnExpression, 0, len(columns)) + unambiguousColumns := make([]*physicalpb.ColumnExpression, 0, len(columns)) + for _, col := range columns { + // Only collect ambiguous columns (might need parsing) + // Skip labels (from stream selector) and builtins (like timestamp/message) + if col.Type == physicalpb.COLUMN_TYPE_AMBIGUOUS { + ambiguousColumns = append(ambiguousColumns, col) + } else { + unambiguousColumns = append(unambiguousColumns, col) + } + } + + return unambiguousColumns, ambiguousColumns +} + // optimization represents a single optimization pass and can hold multiple rules. type optimization struct { - plan *Plan + plan *physicalpb.Plan name string rules []rule } -func newOptimization(name string, plan *Plan) *optimization { +func newOptimization(name string, plan *physicalpb.Plan) *optimization { return &optimization{ name: name, plan: plan, @@ -548,7 +539,7 @@ func (o *optimization) withRules(rules ...rule) *optimization { return o } -func (o *optimization) optimize(node Node) { +func (o *optimization) optimize(node physicalpb.Node) { iterations, maxIterations := 0, 10 for iterations < maxIterations { @@ -561,7 +552,7 @@ func (o *optimization) optimize(node Node) { } } -func (o *optimization) applyRules(node Node) bool { +func (o *optimization) applyRules(node physicalpb.Node) bool { anyChanged := false for _, rule := range o.rules { @@ -575,73 +566,51 @@ func (o *optimization) applyRules(node Node) bool { // The optimizer can optimize physical plans using the provided optimization passes. type optimizer struct { - plan *Plan + plan *physicalpb.Plan optimisations []*optimization } -func newOptimizer(plan *Plan, passes []*optimization) *optimizer { +func newOptimizer(plan *physicalpb.Plan, passes []*optimization) *optimizer { return &optimizer{plan: plan, optimisations: passes} } -func (o *optimizer) optimize(node Node) { +func (o *optimizer) optimize(node physicalpb.Node) { for _, optimisation := range o.optimisations { optimisation.optimize(node) } } -func extractColumnsFromPredicates(predicates []Expression) []ColumnExpression { - columns := make([]ColumnExpression, 0, len(predicates)) +func extractColumnsFromPredicates(predicates []*physicalpb.Expression) []*physicalpb.ColumnExpression { + columns := make([]*physicalpb.ColumnExpression, 0, len(predicates)) for _, p := range predicates { - extractColumnsFromExpression(p, &columns) + extractColumnsFromExpression(*p, &columns) } return deduplicateColumns(columns) } -func extractColumnsFromExpression(expr Expression, columns *[]ColumnExpression) { - switch e := expr.(type) { - case *ColumnExpr: - *columns = append(*columns, e) - case *BinaryExpr: - extractColumnsFromExpression(e.Left, columns) - extractColumnsFromExpression(e.Right, columns) - case *UnaryExpr: - extractColumnsFromExpression(e.Left, columns) +func extractColumnsFromExpression(expr physicalpb.Expression, columns *[]*physicalpb.ColumnExpression) { + switch ex := expr.Kind.(type) { + case *physicalpb.Expression_ColumnExpression: + *columns = append(*columns, ex.ColumnExpression) + case *physicalpb.Expression_BinaryExpression: + extractColumnsFromExpression(*ex.BinaryExpression.Left, columns) + extractColumnsFromExpression(*ex.BinaryExpression.Right, columns) + case *physicalpb.Expression_UnaryExpression: + extractColumnsFromExpression(*ex.UnaryExpression.Value, columns) default: // Ignore other expression types } } -// disambiguateColumns splits columns into ambiguous and unambiguous columns -func disambiguateColumns(columns []ColumnExpression) ([]ColumnExpression, []ColumnExpression) { - ambiguousColumns := make([]ColumnExpression, 0, len(columns)) - unambiguousColumns := make([]ColumnExpression, 0, len(columns)) - for _, col := range columns { - if colExpr, ok := col.(*ColumnExpr); ok { - // Only collect ambiguous columns (might need parsing) - // Skip labels (from stream selector) and builtins (like timestamp/message) - if colExpr.Ref.Type == types.ColumnTypeAmbiguous { - ambiguousColumns = append(ambiguousColumns, col) - } else { - unambiguousColumns = append(unambiguousColumns, col) - } - } - } - - return unambiguousColumns, ambiguousColumns -} - -func deduplicateColumns(columns []ColumnExpression) []ColumnExpression { +func deduplicateColumns(columns []*physicalpb.ColumnExpression) []*physicalpb.ColumnExpression { seen := make(map[string]bool) - var result []ColumnExpression + var result []*physicalpb.ColumnExpression for _, col := range columns { - if colExpr, ok := col.(*ColumnExpr); ok { - key := colExpr.Ref.Column - if !seen[key] { - seen[key] = true - result = append(result, col) - } + if !seen[col.Name] { + seen[col.Name] = true + result = append(result, col) } } @@ -649,28 +618,26 @@ func deduplicateColumns(columns []ColumnExpression) []ColumnExpression { } // addUniqueColumnExpr adds a column to the projections list if it's not already present -func addUniqueColumnExpr(projections []ColumnExpression, colExpr *ColumnExpr) ([]ColumnExpression, bool) { +func addUniqueColumnExpr(projections []*physicalpb.ColumnExpression, colExpr *physicalpb.ColumnExpression) ([]*physicalpb.ColumnExpression, bool) { for _, existing := range projections { - if existingCol, ok := existing.(*ColumnExpr); ok { - if existingCol.Ref.Column == colExpr.Ref.Column { - return projections, false // already exists - } + if existing.Name == colExpr.Name { + return projections, false // already exists } } return append(projections, colExpr), true } // findMatchingNodes finds all nodes in the plan tree that match the given matchFn. -func findMatchingNodes(plan *Plan, root Node, matchFn func(Node) bool) []Node { - var result []Node +func findMatchingNodes(plan *physicalpb.Plan, root physicalpb.Node, matchFn func(physicalpb.Node) bool) []physicalpb.Node { + var result []physicalpb.Node // Using PostOrderWalk to return child nodes first. // This can be useful for optimizations like predicate pushdown // where it is ideal to process child Filter before parent Filter. - _ = plan.graph.Walk(root, func(node Node) error { + _ = plan.Walk(root, func(node physicalpb.Node) error { if matchFn(node) { result = append(result, node) } return nil - }, dag.PostOrderWalk) + }, physicalpb.POST_ORDER_WALK) return result } diff --git a/pkg/engine/internal/planner/physical/optimizer_test.go b/pkg/engine/internal/planner/physical/optimizer_test.go index 9db0455446875..27451218b66a9 100644 --- a/pkg/engine/internal/planner/physical/optimizer_test.go +++ b/pkg/engine/internal/planner/physical/optimizer_test.go @@ -1,6 +1,7 @@ package physical import ( + "fmt" "sort" "testing" "time" @@ -9,57 +10,55 @@ import ( "github.com/grafana/loki/v3/pkg/dataobj/metastore" "github.com/grafana/loki/v3/pkg/engine/internal/planner/logical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" + "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid" ) func TestCanApplyPredicate(t *testing.T) { tests := []struct { - predicate Expression + predicate physicalpb.Expression want bool }{ { - predicate: NewLiteral(int64(123)), + predicate: *NewLiteral(int64(123)).ToExpression(), want: true, }, { - predicate: newColumnExpr("timestamp", types.ColumnTypeBuiltin), + predicate: *newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN).ToExpression(), want: true, }, { - predicate: newColumnExpr("foo", types.ColumnTypeLabel), + predicate: *newColumnExpr("foo", physicalpb.COLUMN_TYPE_LABEL).ToExpression(), want: false, }, { - predicate: &BinaryExpr{ - Left: newColumnExpr("timestamp", types.ColumnTypeBuiltin), - Right: NewLiteral(types.Timestamp(3600000)), - Op: types.BinaryOpGt, - }, + predicate: *newBinaryExpr(newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN).ToExpression(), + NewLiteral(types.Timestamp(3600000)).ToExpression(), + physicalpb.BINARY_OP_GT, + ).ToExpression(), want: true, }, { - predicate: &BinaryExpr{ - Left: newColumnExpr("level", types.ColumnTypeAmbiguous), - Right: NewLiteral("debug|info"), - Op: types.BinaryOpMatchRe, - }, + predicate: *(newBinaryExpr(newColumnExpr("level", physicalpb.COLUMN_TYPE_AMBIGUOUS).ToExpression(), + NewLiteral("debug|info").ToExpression(), + physicalpb.BINARY_OP_MATCH_RE, + )).ToExpression(), want: false, }, { - predicate: &BinaryExpr{ - Left: newColumnExpr("level", types.ColumnTypeMetadata), - Right: NewLiteral("debug|info"), - Op: types.BinaryOpMatchRe, - }, + predicate: *newBinaryExpr(newColumnExpr("level", physicalpb.COLUMN_TYPE_METADATA).ToExpression(), + NewLiteral("debug|info").ToExpression(), + physicalpb.BINARY_OP_MATCH_RE, + ).ToExpression(), want: true, }, { - predicate: &BinaryExpr{ - Left: newColumnExpr("foo", types.ColumnTypeLabel), - Right: NewLiteral("bar"), - Op: types.BinaryOpEq, - }, + predicate: *newBinaryExpr(newColumnExpr("foo", physicalpb.COLUMN_TYPE_LABEL).ToExpression(), + NewLiteral("bar").ToExpression(), + physicalpb.BINARY_OP_EQ, + ).ToExpression(), want: false, }, } @@ -73,36 +72,41 @@ func TestCanApplyPredicate(t *testing.T) { var time1000 = types.Timestamp(1000000000) -func dummyPlan() *Plan { - plan := &Plan{} +var setID = physicalpb.PlanNodeID{Value: ulid.New()} +var filter1ID = physicalpb.PlanNodeID{Value: ulid.New()} +var filter2ID = physicalpb.PlanNodeID{Value: ulid.New()} +var filter3ID = physicalpb.PlanNodeID{Value: ulid.New()} + +func dummyPlan() *physicalpb.Plan { - scanSet := plan.graph.Add(&ScanSet{ - id: "set", + plan := &physicalpb.Plan{} - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanSet := plan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, }) - filter1 := plan.graph.Add(&Filter{id: "filter1", Predicates: []Expression{ - &BinaryExpr{ - Left: newColumnExpr("timestamp", types.ColumnTypeBuiltin), - Right: NewLiteral(time1000), - Op: types.BinaryOpGt, - }, + filter1 := plan.Add(&physicalpb.Filter{Id: filter1ID, Predicates: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN).ToExpression(), + Right: NewLiteral(time1000).ToExpression(), + Op: physicalpb.BINARY_OP_GT, + }).ToExpression(), }}) - filter2 := plan.graph.Add(&Filter{id: "filter2", Predicates: []Expression{ - &BinaryExpr{ - Left: newColumnExpr("level", types.ColumnTypeAmbiguous), - Right: NewLiteral("debug|info"), - Op: types.BinaryOpMatchRe, - }, + filter2 := plan.Add(&physicalpb.Filter{Id: filter2ID, Predicates: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: newColumnExpr("level", physicalpb.COLUMN_TYPE_AMBIGUOUS).ToExpression(), + Right: NewLiteral("debug|info").ToExpression(), + Op: physicalpb.BINARY_OP_MATCH_RE, + }).ToExpression(), }}) - filter3 := plan.graph.Add(&Filter{id: "filter3", Predicates: []Expression{}}) + filter3 := plan.Add(&physicalpb.Filter{Id: filter3ID, Predicates: []*physicalpb.Expression{}}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: filter3, Child: filter2}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: filter2, Child: filter1}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: filter1, Child: scanSet}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter3.GetFilter(), Child: filter2.GetFilter()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter2.GetFilter(), Child: filter1.GetFilter()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter1.GetFilter(), Child: scanSet.GetScanSet()}) return plan } @@ -119,36 +123,35 @@ func TestPredicatePushdown(t *testing.T) { o.optimize(plan.Roots()[0]) actual := PrintAsTree(plan) - optimized := &Plan{} - scanSet := optimized.graph.Add(&ScanSet{ - id: "set", - - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + optimized := &physicalpb.Plan{} + scanSet := optimized.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, - Predicates: []Expression{ - &BinaryExpr{ - Left: newColumnExpr("timestamp", types.ColumnTypeBuiltin), - Right: NewLiteral(time1000), - Op: types.BinaryOpGt, - }, + Predicates: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN).ToExpression(), + Right: NewLiteral(time1000).ToExpression(), + Op: physicalpb.BINARY_OP_GT, + }).ToExpression(), }, }) - filter1 := optimized.graph.Add(&Filter{id: "filter1", Predicates: []Expression{}}) - filter2 := optimized.graph.Add(&Filter{id: "filter2", Predicates: []Expression{ - &BinaryExpr{ - Left: newColumnExpr("level", types.ColumnTypeAmbiguous), - Right: NewLiteral("debug|info"), - Op: types.BinaryOpMatchRe, - }, + filter1 := optimized.Add(&physicalpb.Filter{Id: filter1ID, Predicates: []*physicalpb.Expression{}}) + filter2 := optimized.Add(&physicalpb.Filter{Id: filter2ID, Predicates: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: newColumnExpr("level", physicalpb.COLUMN_TYPE_AMBIGUOUS).ToExpression(), + Right: NewLiteral("debug|info").ToExpression(), + Op: physicalpb.BINARY_OP_MATCH_RE, + }).ToExpression(), }}) // ambiguous column predicates are not pushed down. - filter3 := optimized.graph.Add(&Filter{id: "filter3", Predicates: []Expression{}}) + filter3 := optimized.Add(&physicalpb.Filter{Id: filter3ID, Predicates: []*physicalpb.Expression{}}) - _ = optimized.graph.AddEdge(dag.Edge[Node]{Parent: filter3, Child: filter2}) - _ = optimized.graph.AddEdge(dag.Edge[Node]{Parent: filter2, Child: filter1}) - _ = optimized.graph.AddEdge(dag.Edge[Node]{Parent: filter1, Child: scanSet}) + _ = optimized.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(filter3), Child: physicalpb.GetNode(filter2)}) + _ = optimized.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(filter2), Child: physicalpb.GetNode(filter1)}) + _ = optimized.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(filter1), Child: physicalpb.GetNode(scanSet)}) expected := PrintAsTree(optimized) require.Equal(t, expected, actual) @@ -156,22 +159,26 @@ func TestPredicatePushdown(t *testing.T) { func TestLimitPushdown(t *testing.T) { t.Run("pushdown limit to target nodes", func(t *testing.T) { - plan := &Plan{} + setID := physicalpb.PlanNodeID{Value: ulid.New()} + topK1ID := physicalpb.PlanNodeID{Value: ulid.New()} + topK2ID := physicalpb.PlanNodeID{Value: ulid.New()} + limit1ID := physicalpb.PlanNodeID{Value: ulid.New()} + plan := &physicalpb.Plan{} { - scanset := plan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanset := plan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, }) - topK1 := plan.graph.Add(&TopK{id: "topK1", SortBy: newColumnExpr("timestamp", types.ColumnTypeBuiltin)}) - topK2 := plan.graph.Add(&TopK{id: "topK2", SortBy: newColumnExpr("timestamp", types.ColumnTypeBuiltin)}) - limit := plan.graph.Add(&Limit{id: "limit1", Fetch: 100}) + topK1 := plan.Add(&physicalpb.TopK{Id: topK1ID, SortBy: newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN)}) + topK2 := plan.Add(&physicalpb.TopK{Id: topK2ID, SortBy: newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN)}) + limit := plan.Add(&physicalpb.Limit{Id: limit1ID, Fetch: 100}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: topK1, Child: scanset}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: limit, Child: topK1}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: limit, Child: topK2}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: topK1.GetTopK(), Child: scanset.GetScanSet()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: limit.GetLimit(), Child: topK1.GetTopK()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: limit.GetLimit(), Child: topK2.GetTopK()}) } // apply optimisations @@ -183,22 +190,22 @@ func TestLimitPushdown(t *testing.T) { o := newOptimizer(plan, optimizations) o.optimize(plan.Roots()[0]) - expectedPlan := &Plan{} + expectedPlan := &physicalpb.Plan{} { - scanset := expectedPlan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanset := expectedPlan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, }) - topK1 := expectedPlan.graph.Add(&TopK{id: "topK1", SortBy: newColumnExpr("timestamp", types.ColumnTypeBuiltin), K: 100}) - topK2 := expectedPlan.graph.Add(&TopK{id: "topK2", SortBy: newColumnExpr("timestamp", types.ColumnTypeBuiltin), K: 100}) - limit := expectedPlan.graph.Add(&Limit{id: "limit1", Fetch: 100}) + topK1 := expectedPlan.Add(&physicalpb.TopK{Id: topK1ID, SortBy: newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN), K: 100}) + topK2 := expectedPlan.Add(&physicalpb.TopK{Id: topK2ID, SortBy: newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN), K: 100}) + limit := expectedPlan.Add(&physicalpb.Limit{Id: limit1ID, Fetch: 100}) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: limit, Child: topK1}) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: limit, Child: topK2}) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: topK1, Child: scanset}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: limit.GetLimit(), Child: topK1.GetTopK()}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: limit.GetLimit(), Child: topK2.GetTopK()}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: topK1.GetTopK(), Child: scanset.GetScanSet()}) } actual := PrintAsTree(plan) @@ -208,35 +215,40 @@ func TestLimitPushdown(t *testing.T) { t.Run("pushdown blocked by filter nodes", func(t *testing.T) { // Limit should not be propagated to child nodes when there are filters - filterPredicates := []Expression{ - &BinaryExpr{ - Left: &ColumnExpr{Ref: types.ColumnRef{Column: "level", Type: types.ColumnTypeLabel}}, - Right: NewLiteral("error"), - Op: types.BinaryOpEq, - }, + filterPredicates := []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{Name: "level", Type: physicalpb.COLUMN_TYPE_LABEL}).ToExpression(), + Right: NewLiteral("error").ToExpression(), + Op: physicalpb.BINARY_OP_EQ, + }).ToExpression(), } + setID := physicalpb.PlanNodeID{Value: ulid.New()} + topK1ID := physicalpb.PlanNodeID{Value: ulid.New()} + topK2ID := physicalpb.PlanNodeID{Value: ulid.New()} + limit1ID := physicalpb.PlanNodeID{Value: ulid.New()} + filter1ID := physicalpb.PlanNodeID{Value: ulid.New()} - plan := &Plan{} + plan := &physicalpb.Plan{} { - scanset := plan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanset := plan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, }) - topK1 := plan.graph.Add(&TopK{id: "topK1", SortBy: newColumnExpr("timestamp", types.ColumnTypeBuiltin)}) - topK2 := plan.graph.Add(&TopK{id: "topK2", SortBy: newColumnExpr("timestamp", types.ColumnTypeBuiltin)}) - filter := plan.graph.Add(&Filter{ - id: "filter1", + topK1 := plan.Add(&physicalpb.TopK{Id: topK1ID, SortBy: newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN)}) + topK2 := plan.Add(&physicalpb.TopK{Id: topK2ID, SortBy: newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN)}) + filter := plan.Add(&physicalpb.Filter{ + Id: filter1ID, Predicates: filterPredicates, }) - limit := plan.graph.Add(&Limit{id: "limit1", Fetch: 100}) + limit := plan.Add(&physicalpb.Limit{Id: limit1ID, Fetch: 100}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: limit, Child: filter}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: filter, Child: topK1}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: filter, Child: topK2}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: topK1, Child: scanset}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: limit.GetLimit(), Child: filter.GetFilter()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter.GetFilter(), Child: topK1.GetTopK()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter.GetFilter(), Child: topK2.GetTopK()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: topK1.GetTopK(), Child: scanset.GetScanSet()}) } orig := PrintAsTree(plan) @@ -256,38 +268,41 @@ func TestLimitPushdown(t *testing.T) { func TestGroupByPushdown(t *testing.T) { t.Run("pushdown to RangeAggregation", func(t *testing.T) { - groupBy := []ColumnExpression{ - &ColumnExpr{Ref: types.ColumnRef{Column: "service", Type: types.ColumnTypeLabel}}, - &ColumnExpr{Ref: types.ColumnRef{Column: "level", Type: types.ColumnTypeLabel}}, + setID := physicalpb.PlanNodeID{Value: ulid.New()} + rangeAggID := physicalpb.PlanNodeID{Value: ulid.New()} + sumOfID := physicalpb.PlanNodeID{Value: ulid.New()} + + groupBy := []*physicalpb.ColumnExpression{ + newColumnExpr("service", physicalpb.COLUMN_TYPE_LABEL), + newColumnExpr("level", physicalpb.COLUMN_TYPE_LABEL), } // generate plan for sum by(service, instance) (count_over_time{...}[]) - plan := &Plan{} + plan := &physicalpb.Plan{} { - scanSet := plan.graph.Add(&ScanSet{ - id: "set", + scanSet := plan.Add(&physicalpb.ScanSet{ + Id: setID, - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, - Predicates: []Expression{}, + Predicates: []*physicalpb.Expression{}, }) - rangeAgg := plan.graph.Add(&RangeAggregation{ - id: "count_over_time", - Operation: types.RangeAggregationTypeCount, + rangeAgg := plan.Add(&physicalpb.AggregateRange{ + Id: rangeAggID, + Operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, }) - vectorAgg := plan.graph.Add(&VectorAggregation{ - id: "sum_of", - Operation: types.VectorAggregationTypeSum, + vectorAgg := plan.Add(&physicalpb.AggregateVector{ + Id: sumOfID, + Operation: physicalpb.AGGREGATE_VECTOR_OP_SUM, GroupBy: groupBy, }) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: vectorAgg, Child: rangeAgg}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: scanSet}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: vectorAgg.GetAggregateVector(), Child: rangeAgg.GetAggregateRange()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg.GetAggregateRange(), Child: scanSet.GetScanSet()}) } - // apply optimisation optimizations := []*optimization{ newOptimization("groupBy pushdown", plan).withRules( @@ -297,29 +312,29 @@ func TestGroupByPushdown(t *testing.T) { o := newOptimizer(plan, optimizations) o.optimize(plan.Roots()[0]) - expectedPlan := &Plan{} + expectedPlan := &physicalpb.Plan{} { - scanSet := expectedPlan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanSet := expectedPlan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, - Predicates: []Expression{}, + Predicates: []*physicalpb.Expression{}, }) - rangeAgg := expectedPlan.graph.Add(&RangeAggregation{ - id: "count_over_time", - Operation: types.RangeAggregationTypeCount, + rangeAgg := expectedPlan.Add(&physicalpb.AggregateRange{ + Id: rangeAggID, + Operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, PartitionBy: groupBy, }) - vectorAgg := expectedPlan.graph.Add(&VectorAggregation{ - id: "sum_of", - Operation: types.VectorAggregationTypeSum, + vectorAgg := expectedPlan.Add(&physicalpb.AggregateVector{ + Id: sumOfID, + Operation: physicalpb.AGGREGATE_VECTOR_OP_SUM, GroupBy: groupBy, }) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: vectorAgg, Child: rangeAgg}) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: scanSet}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: vectorAgg.GetAggregateVector(), Child: rangeAgg.GetAggregateRange()}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg.GetAggregateRange(), Child: scanSet.GetScanSet()}) } actual := PrintAsTree(plan) @@ -328,33 +343,36 @@ func TestGroupByPushdown(t *testing.T) { }) t.Run("MAX->SUM is not allowed", func(t *testing.T) { - groupBy := []ColumnExpression{ - &ColumnExpr{Ref: types.ColumnRef{Column: "service", Type: types.ColumnTypeLabel}}, + setID := physicalpb.PlanNodeID{Value: ulid.New()} + rangeAggID := physicalpb.PlanNodeID{Value: ulid.New()} + maxOfID := physicalpb.PlanNodeID{Value: ulid.New()} + groupBy := []*physicalpb.ColumnExpression{ + newColumnExpr("service", physicalpb.COLUMN_TYPE_LABEL), } // generate plan for max by(service) (sum_over_time{...}[]) - plan := &Plan{} + plan := &physicalpb.Plan{} { - scanSet := plan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanSet := plan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, - Predicates: []Expression{}, + Predicates: []*physicalpb.Expression{}, }) - rangeAgg := plan.graph.Add(&RangeAggregation{ - id: "sum_over_time", - Operation: types.RangeAggregationTypeSum, + rangeAgg := plan.Add(&physicalpb.AggregateRange{ + Id: rangeAggID, + Operation: physicalpb.AGGREGATE_RANGE_OP_SUM, }) - vectorAgg := plan.graph.Add(&VectorAggregation{ - id: "max_of", - Operation: types.VectorAggregationTypeMax, + vectorAgg := plan.Add(&physicalpb.AggregateVector{ + Id: maxOfID, + Operation: physicalpb.AGGREGATE_VECTOR_OP_MAX, GroupBy: groupBy, }) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: vectorAgg, Child: rangeAgg}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: scanSet}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: vectorAgg.GetAggregateVector(), Child: rangeAgg.GetAggregateRange()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg.GetAggregateRange(), Child: scanSet.GetScanSet()}) } orig := PrintAsTree(plan) @@ -375,27 +393,28 @@ func TestGroupByPushdown(t *testing.T) { func TestProjectionPushdown(t *testing.T) { t.Run("range aggreagation groupBy -> scanset", func(t *testing.T) { - partitionBy := []ColumnExpression{ - &ColumnExpr{Ref: types.ColumnRef{Column: "level", Type: types.ColumnTypeLabel}}, - &ColumnExpr{Ref: types.ColumnRef{Column: "service", Type: types.ColumnTypeLabel}}, + partitionBy := []*physicalpb.ColumnExpression{ + {Name: "level", Type: physicalpb.COLUMN_TYPE_LABEL}, + {Name: "service", Type: physicalpb.COLUMN_TYPE_LABEL}, } - - plan := &Plan{} + setID := physicalpb.PlanNodeID{Value: ulid.New()} + range1ID := physicalpb.PlanNodeID{Value: ulid.New()} + plan := &physicalpb.Plan{} { - scanset := plan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanset := plan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, }) - rangeAgg := plan.graph.Add(&RangeAggregation{ - id: "range1", - Operation: types.RangeAggregationTypeCount, + rangeAgg := plan.Add(&physicalpb.AggregateRange{ + Id: range1ID, + Operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, PartitionBy: partitionBy, }) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: scanset}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg.GetAggregateRange(), Child: scanset.GetScanSet()}) } // apply optimisations @@ -407,25 +426,25 @@ func TestProjectionPushdown(t *testing.T) { o := newOptimizer(plan, optimizations) o.optimize(plan.Roots()[0]) - expectedPlan := &Plan{} + expectedPlan := &physicalpb.Plan{} { - projected := append(partitionBy, &ColumnExpr{Ref: types.ColumnRef{Column: types.ColumnNameBuiltinTimestamp, Type: types.ColumnTypeBuiltin}}) - scanset := expectedPlan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + projected := append(partitionBy, &physicalpb.ColumnExpression{Name: types.ColumnNameBuiltinTimestamp, Type: physicalpb.COLUMN_TYPE_BUILTIN}) + scanset := expectedPlan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, Projections: projected, }) - rangeAgg := expectedPlan.graph.Add(&RangeAggregation{ - id: "range1", - Operation: types.RangeAggregationTypeCount, + rangeAgg := expectedPlan.Add(&physicalpb.AggregateRange{ + Id: range1ID, + Operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, PartitionBy: partitionBy, }) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: scanset}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg.GetAggregateRange(), Child: scanset.GetScanSet()}) } actual := PrintAsTree(plan) @@ -434,42 +453,45 @@ func TestProjectionPushdown(t *testing.T) { }) t.Run("filter -> scanset", func(t *testing.T) { - filterPredicates := []Expression{ - &BinaryExpr{ - Left: &ColumnExpr{Ref: types.ColumnRef{Column: "level", Type: types.ColumnTypeLabel}}, - Right: NewLiteral("error"), - Op: types.BinaryOpEq, - }, - &BinaryExpr{ - Left: &ColumnExpr{Ref: types.ColumnRef{Column: "message", Type: types.ColumnTypeBuiltin}}, - Right: NewLiteral(".*exception.*"), - Op: types.BinaryOpMatchRe, - }, + filterPredicates := []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{Name: "level", Type: physicalpb.COLUMN_TYPE_LABEL}).ToExpression(), + Right: NewLiteral("error").ToExpression(), + Op: physicalpb.BINARY_OP_EQ, + }).ToExpression(), + (&physicalpb.BinaryExpression{ + Left: (&physicalpb.ColumnExpression{Name: "message", Type: physicalpb.COLUMN_TYPE_BUILTIN}).ToExpression(), + Right: NewLiteral(".*exception.*").ToExpression(), + Op: physicalpb.BINARY_OP_MATCH_RE, + }).ToExpression(), } - plan := &Plan{} + setID := physicalpb.PlanNodeID{Value: ulid.New()} + filter1ID := physicalpb.PlanNodeID{Value: ulid.New()} + range1ID := physicalpb.PlanNodeID{Value: ulid.New()} + plan := &physicalpb.Plan{} { - scanset := plan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanset := plan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, - Projections: []ColumnExpression{ - &ColumnExpr{Ref: types.ColumnRef{Column: "existing", Type: types.ColumnTypeLabel}}, + Projections: []*physicalpb.ColumnExpression{ + {Name: "existing", Type: physicalpb.COLUMN_TYPE_LABEL}, }, }) - filter := plan.graph.Add(&Filter{ - id: "filter1", + filter := plan.Add(&physicalpb.Filter{ + Id: filter1ID, Predicates: filterPredicates, }) - rangeAgg := plan.graph.Add(&RangeAggregation{ - id: "range1", - Operation: types.RangeAggregationTypeCount, + rangeAgg := plan.Add(&physicalpb.AggregateRange{ + Id: range1ID, + Operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, }) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: filter}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: filter, Child: scanset}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg.GetAggregateRange(), Child: filter.GetFilter()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter.GetFilter(), Child: scanset.GetScanSet()}) } // apply optimisations @@ -481,34 +503,34 @@ func TestProjectionPushdown(t *testing.T) { o := newOptimizer(plan, optimizations) o.optimize(plan.Roots()[0]) - expectedPlan := &Plan{} + expectedPlan := &physicalpb.Plan{} { - expectedProjections := []ColumnExpression{ - &ColumnExpr{Ref: types.ColumnRef{Column: "existing", Type: types.ColumnTypeLabel}}, - &ColumnExpr{Ref: types.ColumnRef{Column: "level", Type: types.ColumnTypeLabel}}, - &ColumnExpr{Ref: types.ColumnRef{Column: "message", Type: types.ColumnTypeBuiltin}}, - &ColumnExpr{Ref: types.ColumnRef{Column: types.ColumnNameBuiltinTimestamp, Type: types.ColumnTypeBuiltin}}, + expectedProjections := []*physicalpb.ColumnExpression{ + {Name: "existing", Type: physicalpb.COLUMN_TYPE_LABEL}, + {Name: "level", Type: physicalpb.COLUMN_TYPE_LABEL}, + {Name: "message", Type: physicalpb.COLUMN_TYPE_BUILTIN}, + {Name: types.ColumnNameBuiltinTimestamp, Type: physicalpb.COLUMN_TYPE_BUILTIN}, } - scanset := expectedPlan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanset := expectedPlan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, Projections: expectedProjections, }) - filter := expectedPlan.graph.Add(&Filter{ - id: "filter1", + filter := expectedPlan.Add(&physicalpb.Filter{ + Id: filter1ID, Predicates: filterPredicates, }) - rangeAgg := expectedPlan.graph.Add(&RangeAggregation{ - id: "range1", - Operation: types.RangeAggregationTypeCount, + rangeAgg := expectedPlan.Add(&physicalpb.AggregateRange{ + Id: range1ID, + Operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, }) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: filter}) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: filter, Child: scanset}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg.GetAggregateRange(), Child: filter.GetFilter()}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter.GetFilter(), Child: scanset.GetScanSet()}) } actual := PrintAsTree(plan) @@ -517,36 +539,39 @@ func TestProjectionPushdown(t *testing.T) { }) t.Run("unwrap -> scanset", func(t *testing.T) { - plan := &Plan{} + setID := physicalpb.PlanNodeID{Value: ulid.New()} + project1ID := physicalpb.PlanNodeID{Value: ulid.New()} + range1ID := physicalpb.PlanNodeID{Value: ulid.New()} + plan := &physicalpb.Plan{} { - scanset := plan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanset := plan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, - Projections: []ColumnExpression{ - &ColumnExpr{Ref: types.ColumnRef{Column: "existing", Type: types.ColumnTypeLabel}}, + Projections: []*physicalpb.ColumnExpression{ + {Name: "existing", Type: physicalpb.COLUMN_TYPE_LABEL}, }, }) - project := plan.graph.Add(&Projection{ - id: "project1", + project := plan.Add(&physicalpb.Projection{ + Id: project1ID, Expand: true, - Expressions: []Expression{ - &UnaryExpr{ - Op: types.UnaryOpCastFloat, - Left: &ColumnExpr{Ref: types.ColumnRef{Column: "rows", Type: types.ColumnTypeAmbiguous}}, - }, + Expressions: []*physicalpb.Expression{ + (&physicalpb.UnaryExpression{ + Op: physicalpb.UNARY_OP_CAST_FLOAT, + Value: (&physicalpb.ColumnExpression{Name: "rows", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), + }).ToExpression(), }, }) - rangeAgg := plan.graph.Add(&RangeAggregation{ - id: "range1", - Operation: types.RangeAggregationTypeCount, + rangeAgg := plan.Add(&physicalpb.AggregateRange{ + Id: range1ID, + Operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, }) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: project}) - _ = plan.graph.AddEdge(dag.Edge[Node]{Parent: project, Child: scanset}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg.GetAggregateRange(), Child: project.GetProjection()}) + _ = plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: project.GetProjection(), Child: scanset.GetScanSet()}) } // apply optimisations @@ -558,39 +583,39 @@ func TestProjectionPushdown(t *testing.T) { o := newOptimizer(plan, optimizations) o.optimize(plan.Roots()[0]) - expectedPlan := &Plan{} + expectedPlan := &physicalpb.Plan{} { - expectedProjections := []ColumnExpression{ - &ColumnExpr{Ref: types.ColumnRef{Column: "existing", Type: types.ColumnTypeLabel}}, - &ColumnExpr{Ref: types.ColumnRef{Column: "rows", Type: types.ColumnTypeAmbiguous}}, - &ColumnExpr{Ref: types.ColumnRef{Column: types.ColumnNameBuiltinTimestamp, Type: types.ColumnTypeBuiltin}}, + expectedProjections := []*physicalpb.ColumnExpression{ + {Name: "existing", Type: physicalpb.COLUMN_TYPE_LABEL}, + {Name: "rows", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}, + {Name: types.ColumnNameBuiltinTimestamp, Type: physicalpb.COLUMN_TYPE_BUILTIN}, } - scanset := expectedPlan.graph.Add(&ScanSet{ - id: "set", - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + scanset := expectedPlan.Add(&physicalpb.ScanSet{ + Id: setID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, Projections: expectedProjections, }) - project := expectedPlan.graph.Add(&Projection{ - id: "project1", + project := expectedPlan.Add(&physicalpb.Projection{ + Id: project1ID, Expand: true, - Expressions: []Expression{ - &UnaryExpr{ - Op: types.UnaryOpCastFloat, - Left: &ColumnExpr{Ref: types.ColumnRef{Column: "rows", Type: types.ColumnTypeAmbiguous}}, - }, + Expressions: []*physicalpb.Expression{ + (&physicalpb.UnaryExpression{ + Op: physicalpb.UNARY_OP_CAST_FLOAT, + Value: (&physicalpb.ColumnExpression{Name: "rows", Type: physicalpb.COLUMN_TYPE_AMBIGUOUS}).ToExpression(), + }).ToExpression(), }, }) - rangeAgg := expectedPlan.graph.Add(&RangeAggregation{ - id: "range1", - Operation: types.RangeAggregationTypeCount, + rangeAgg := expectedPlan.Add(&physicalpb.AggregateRange{ + Id: range1ID, + Operation: physicalpb.AGGREGATE_RANGE_OP_COUNT, }) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: project}) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: project, Child: scanset}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg.GetAggregateRange(), Child: project.GetProjection()}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(project), Child: physicalpb.GetNode(scanset)}) } actual := PrintAsTree(plan) @@ -660,7 +685,7 @@ func TestProjectionPushdown_PushesRequestedKeysToParseNodes(t *testing.T) { name: "ParseNode skips label and builtin columns, only collects ambiguous", buildLogical: func() logical.Value { // {app="test"} | logfmt | app="frontend" | level="error" - // This is a log query (no RangeAggregation) so should parse all keys + // This is a log query (no physicalpb.AggregateRange) so should parse all keys builder := logical.NewBuilder(&logical.MakeTable{ Selector: &logical.BinOp{ Left: logical.NewColumnRef("app", types.ColumnTypeLabel), @@ -702,7 +727,7 @@ func TestProjectionPushdown_PushesRequestedKeysToParseNodes(t *testing.T) { expectedDataObjScanProjections: []string{"app", "level", "message", "timestamp"}, }, { - name: "ParseNode collects RangeAggregation PartitionBy ambiguous columns", + name: "ParseNode collects AggregateRange PartitionBy ambiguous columns", buildLogical: func() logical.Value { // count_over_time({app="test"} | logfmt [5m]) by (duration, service) builder := logical.NewBuilder(&logical.MakeTable{ @@ -804,6 +829,9 @@ func TestProjectionPushdown_PushesRequestedKeysToParseNodes(t *testing.T) { } ctx := NewContext(time.Unix(0, 0), time.Unix(3600, 0)) planner := NewPlanner(ctx, catalog) + if tt.expectedParseKeysRequested != nil { + fmt.Println("Interesting test case") + } // Build physical plan physicalPlan, err := planner.Build(logicalPlan) @@ -814,17 +842,17 @@ func TestProjectionPushdown_PushesRequestedKeysToParseNodes(t *testing.T) { require.NoError(t, err) // Check that ParseNode and DataObjScan get the correct projections - var parseNode *ParseNode + var parseNode *physicalpb.Parse projections := map[string]struct{}{} - for node := range optimizedPlan.graph.Nodes() { - if pn, ok := node.(*ParseNode); ok { - parseNode = pn + for _, node := range optimizedPlan.Nodes { + switch kind := node.Kind.(type) { + case *physicalpb.PlanNode_Parse: + parseNode = kind.Parse continue } - if pn, ok := node.(*ScanSet); ok { - for _, colExpr := range pn.Projections { - expr := colExpr.(*ColumnExpr) - projections[expr.Ref.Column] = struct{}{} + if pn, ok := node.Kind.(*physicalpb.PlanNode_ScanSet); ok { + for _, colExpr := range pn.ScanSet.Projections { + projections[colExpr.Name] = struct{}{} } } } @@ -854,34 +882,34 @@ func TestRemoveNoopFilter(t *testing.T) { o.optimize(plan.Roots()[0]) actual := PrintAsTree(plan) - optimized := &Plan{} - scanSet := optimized.graph.Add(&ScanSet{ - id: "set", + optimized := &physicalpb.Plan{} + scanSet := optimized.Add(&physicalpb.ScanSet{ + Id: setID, - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, - Predicates: []Expression{}, + Predicates: []*physicalpb.Expression{}, }) - filter1 := optimized.graph.Add(&Filter{id: "filter1", Predicates: []Expression{ - &BinaryExpr{ - Left: newColumnExpr("timestamp", types.ColumnTypeBuiltin), - Right: NewLiteral(time1000), - Op: types.BinaryOpGt, - }, + filter1 := optimized.Add(&physicalpb.Filter{Id: filter1ID, Predicates: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: newColumnExpr("timestamp", physicalpb.COLUMN_TYPE_BUILTIN).ToExpression(), + Right: NewLiteral(time1000).ToExpression(), + Op: physicalpb.BINARY_OP_GT, + }).ToExpression(), }}) - filter2 := optimized.graph.Add(&Filter{id: "filter2", Predicates: []Expression{ - &BinaryExpr{ - Left: newColumnExpr("level", types.ColumnTypeAmbiguous), - Right: NewLiteral("debug|info"), - Op: types.BinaryOpMatchRe, - }, + filter2 := optimized.Add(&physicalpb.Filter{Id: filter2ID, Predicates: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ + Left: newColumnExpr("level", physicalpb.COLUMN_TYPE_AMBIGUOUS).ToExpression(), + Right: NewLiteral("debug|info").ToExpression(), + Op: physicalpb.BINARY_OP_MATCH_RE, + }).ToExpression(), }}) - _ = optimized.graph.AddEdge(dag.Edge[Node]{Parent: filter2, Child: filter1}) - _ = optimized.graph.AddEdge(dag.Edge[Node]{Parent: filter1, Child: scanSet}) + _ = optimized.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter2.GetFilter(), Child: filter1.GetFilter()}) + _ = optimized.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter1.GetFilter(), Child: scanSet.GetScanSet()}) expected := PrintAsTree(optimized) require.Equal(t, expected, actual) @@ -891,7 +919,7 @@ func Test_parallelPushdown(t *testing.T) { t.Run("canPushdown", func(t *testing.T) { tt := []struct { name string - children []Node + children []physicalpb.Node expected bool }{ { @@ -901,75 +929,80 @@ func Test_parallelPushdown(t *testing.T) { }, { name: "one child (not Parallelize)", - children: []Node{&DataObjScan{}}, + children: []physicalpb.Node{&physicalpb.DataObjScan{Id: physicalpb.PlanNodeID{Value: ulid.New()}}}, expected: false, }, { name: "one child (Parallelize)", - children: []Node{&Parallelize{}}, + children: []physicalpb.Node{&physicalpb.Parallelize{Id: physicalpb.PlanNodeID{Value: ulid.New()}}}, expected: true, }, { name: "multiple children (all Parallelize)", - children: []Node{&Parallelize{}, &Parallelize{}}, + children: []physicalpb.Node{&physicalpb.Parallelize{Id: physicalpb.PlanNodeID{Value: ulid.New()}}, &physicalpb.Parallelize{Id: physicalpb.PlanNodeID{Value: ulid.New()}}}, expected: true, }, { name: "multiple children (not all Parallelize)", - children: []Node{&Parallelize{}, &DataObjScan{}}, + children: []physicalpb.Node{&physicalpb.Parallelize{Id: physicalpb.PlanNodeID{Value: ulid.New()}}, &physicalpb.DataObjScan{Id: physicalpb.PlanNodeID{Value: ulid.New()}}}, expected: false, }, } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { - var plan Plan - parent := plan.graph.Add(&Filter{}) + var plan physicalpb.Plan + parent := plan.Add(&physicalpb.Filter{}) for _, child := range tc.children { - plan.graph.Add(child) - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: parent, Child: child})) + plan.Add(child) + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parent), Child: child})) } pass := parallelPushdown{plan: &plan} - require.Equal(t, tc.expected, pass.canPushdown(parent)) + require.Equal(t, tc.expected, pass.canPushdown(physicalpb.GetNode(parent))) }) } }) t.Run("Shifts Filter", func(t *testing.T) { - var plan Plan + var plan physicalpb.Plan + vectorAggID := physicalpb.PlanNodeID{Value: ulid.New()} + rangeAggID := physicalpb.PlanNodeID{Value: ulid.New()} + filterID := physicalpb.PlanNodeID{Value: ulid.New()} + parallelizeID := physicalpb.PlanNodeID{Value: ulid.New()} + scanID := physicalpb.PlanNodeID{Value: ulid.New()} { - vectorAgg := plan.graph.Add(&VectorAggregation{}) - rangeAgg := plan.graph.Add(&RangeAggregation{}) - filter := plan.graph.Add(&Filter{}) - parallelize := plan.graph.Add(&Parallelize{}) - scan := plan.graph.Add(&DataObjScan{}) - - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: vectorAgg, Child: rangeAgg})) - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: filter})) - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: filter, Child: parallelize})) - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: parallelize, Child: scan})) + vectorAgg := plan.Add(&physicalpb.AggregateVector{Id: vectorAggID}) + rangeAgg := plan.Add(&physicalpb.AggregateRange{Id: rangeAggID}) + filter := plan.Add(&physicalpb.Filter{Id: filterID}) + parallelize := plan.Add(&physicalpb.Parallelize{Id: parallelizeID}) + scan := plan.Add(&physicalpb.DataObjScan{Id: scanID}) + + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(vectorAgg), Child: physicalpb.GetNode(rangeAgg)})) + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(rangeAgg), Child: physicalpb.GetNode(filter)})) + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(filter), Child: physicalpb.GetNode(parallelize)})) + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parallelize), Child: physicalpb.GetNode(scan)})) } opt := newOptimizer(&plan, []*optimization{ newOptimization("ParallelPushdown", &plan).withRules(¶llelPushdown{plan: &plan}), }) - root, _ := plan.graph.Root() + root, _ := plan.Root() opt.optimize(root) - var expectedPlan Plan + var expectedPlan physicalpb.Plan { - vectorAgg := expectedPlan.graph.Add(&VectorAggregation{}) - rangeAgg := expectedPlan.graph.Add(&RangeAggregation{}) - parallelize := expectedPlan.graph.Add(&Parallelize{}) - filter := expectedPlan.graph.Add(&Filter{}) - scan := expectedPlan.graph.Add(&DataObjScan{}) - - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: vectorAgg, Child: rangeAgg})) - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: parallelize})) - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: parallelize, Child: filter})) - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: filter, Child: scan})) + vectorAgg := expectedPlan.Add(&physicalpb.AggregateVector{Id: vectorAggID}) + rangeAgg := expectedPlan.Add(&physicalpb.AggregateRange{Id: rangeAggID}) + parallelize := expectedPlan.Add(&physicalpb.Parallelize{Id: parallelizeID}) + filter := expectedPlan.Add(&physicalpb.Filter{Id: filterID}) + scan := expectedPlan.Add(&physicalpb.DataObjScan{Id: scanID}) + + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(vectorAgg), Child: physicalpb.GetNode(rangeAgg)})) + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(rangeAgg), Child: physicalpb.GetNode(parallelize)})) + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parallelize), Child: physicalpb.GetNode(filter)})) + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(filter), Child: physicalpb.GetNode(scan)})) } expected := PrintAsTree(&expectedPlan) @@ -977,38 +1010,43 @@ func Test_parallelPushdown(t *testing.T) { }) t.Run("Shifts Parse", func(t *testing.T) { - var plan Plan + var plan physicalpb.Plan + vectorAggID := physicalpb.PlanNodeID{Value: ulid.New()} + rangeAggID := physicalpb.PlanNodeID{Value: ulid.New()} + parseID := physicalpb.PlanNodeID{Value: ulid.New()} + parallelizeID := physicalpb.PlanNodeID{Value: ulid.New()} + scanID := physicalpb.PlanNodeID{Value: ulid.New()} { - vectorAgg := plan.graph.Add(&VectorAggregation{}) - rangeAgg := plan.graph.Add(&RangeAggregation{}) - parse := plan.graph.Add(&ParseNode{}) - parallelize := plan.graph.Add(&Parallelize{}) - scan := plan.graph.Add(&DataObjScan{}) - - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: vectorAgg, Child: rangeAgg})) - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: parse})) - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: parse, Child: parallelize})) - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: parallelize, Child: scan})) + vectorAgg := plan.Add(&physicalpb.AggregateVector{Id: vectorAggID}) + rangeAgg := plan.Add(&physicalpb.AggregateRange{Id: rangeAggID}) + parse := plan.Add(&physicalpb.Parse{Id: parseID}) + parallelize := plan.Add(&physicalpb.Parallelize{Id: parallelizeID}) + scan := plan.Add(&physicalpb.DataObjScan{Id: scanID}) + + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(vectorAgg), Child: physicalpb.GetNode(rangeAgg)})) + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(rangeAgg), Child: physicalpb.GetNode(parse)})) + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parse), Child: physicalpb.GetNode(parallelize)})) + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parallelize), Child: physicalpb.GetNode(scan)})) } opt := newOptimizer(&plan, []*optimization{ newOptimization("ParallelPushdown", &plan).withRules(¶llelPushdown{plan: &plan}), }) - root, _ := plan.graph.Root() + root, _ := plan.Root() opt.optimize(root) - var expectedPlan Plan + var expectedPlan physicalpb.Plan { - vectorAgg := expectedPlan.graph.Add(&VectorAggregation{}) - rangeAgg := expectedPlan.graph.Add(&RangeAggregation{}) - parallelize := expectedPlan.graph.Add(&Parallelize{}) - parse := expectedPlan.graph.Add(&ParseNode{}) - scan := expectedPlan.graph.Add(&DataObjScan{}) - - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: vectorAgg, Child: rangeAgg})) - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: rangeAgg, Child: parallelize})) - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: parallelize, Child: parse})) - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: parse, Child: scan})) + vectorAgg := expectedPlan.Add(&physicalpb.AggregateVector{Id: vectorAggID}) + rangeAgg := expectedPlan.Add(&physicalpb.AggregateRange{Id: rangeAggID}) + parallelize := expectedPlan.Add(&physicalpb.Parallelize{Id: parallelizeID}) + parse := expectedPlan.Add(&physicalpb.Parse{Id: parseID}) + scan := expectedPlan.Add(&physicalpb.DataObjScan{Id: scanID}) + + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(vectorAgg), Child: physicalpb.GetNode(rangeAgg)})) + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(rangeAgg), Child: physicalpb.GetNode(parallelize)})) + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parallelize), Child: physicalpb.GetNode(parse)})) + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parse), Child: physicalpb.GetNode(scan)})) } expected := PrintAsTree(&expectedPlan) @@ -1016,22 +1054,28 @@ func Test_parallelPushdown(t *testing.T) { }) t.Run("Splits TopK", func(t *testing.T) { - var plan Plan + var plan physicalpb.Plan + limitID := physicalpb.PlanNodeID{Value: ulid.New()} + topKID := physicalpb.PlanNodeID{Value: ulid.New()} + parallelizeID := physicalpb.PlanNodeID{Value: ulid.New()} + scanID := physicalpb.PlanNodeID{Value: ulid.New()} + globalTopKID := physicalpb.PlanNodeID{Value: ulid.New()} + localTopKID := physicalpb.PlanNodeID{Value: ulid.New()} { - limit := plan.graph.Add(&Limit{}) - topk := plan.graph.Add(&TopK{SortBy: &ColumnExpr{}}) - parallelize := plan.graph.Add(&Parallelize{}) - scan := plan.graph.Add(&DataObjScan{}) - - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: limit, Child: topk})) - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: topk, Child: parallelize})) - require.NoError(t, plan.graph.AddEdge(dag.Edge[Node]{Parent: parallelize, Child: scan})) + limit := plan.Add(&physicalpb.Limit{Id: limitID}) + topk := plan.Add(&physicalpb.TopK{SortBy: &physicalpb.ColumnExpression{}, Id: topKID}) + parallelize := plan.Add(&physicalpb.Parallelize{Id: parallelizeID}) + scan := plan.Add(&physicalpb.DataObjScan{Id: scanID}) + + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(limit), Child: physicalpb.GetNode(topk)})) + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(topk), Child: physicalpb.GetNode(parallelize)})) + require.NoError(t, plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parallelize), Child: physicalpb.GetNode(scan)})) } opt := newOptimizer(&plan, []*optimization{ newOptimization("ParallelPushdown", &plan).withRules(¶llelPushdown{plan: &plan}), }) - root, _ := plan.graph.Root() + root, _ := plan.Root() // Since [optimization.optimize] does up to three passes, // parallelPushdown must ignore a node after it's already been @@ -1046,18 +1090,18 @@ func Test_parallelPushdown(t *testing.T) { // DataObjScan opt.optimize(root) - var expectedPlan Plan + var expectedPlan physicalpb.Plan { - limit := expectedPlan.graph.Add(&Limit{}) - globalTopK := expectedPlan.graph.Add(&TopK{SortBy: &ColumnExpr{}}) - parallelize := expectedPlan.graph.Add(&Parallelize{}) - localTopK := expectedPlan.graph.Add(&TopK{SortBy: &ColumnExpr{}}) - scan := expectedPlan.graph.Add(&DataObjScan{}) - - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: limit, Child: globalTopK})) - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: globalTopK, Child: parallelize})) - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: parallelize, Child: localTopK})) - require.NoError(t, expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: localTopK, Child: scan})) + limit := expectedPlan.Add(&physicalpb.Limit{Id: limitID}) + globalTopK := expectedPlan.Add(&physicalpb.TopK{Id: globalTopKID, SortBy: &physicalpb.ColumnExpression{}}) + parallelize := expectedPlan.Add(&physicalpb.Parallelize{Id: parallelizeID}) + localTopK := expectedPlan.Add(&physicalpb.TopK{Id: localTopKID, SortBy: &physicalpb.ColumnExpression{}}) + scan := expectedPlan.Add(&physicalpb.DataObjScan{Id: scanID}) + + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(limit), Child: physicalpb.GetNode(globalTopK)})) + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(globalTopK), Child: physicalpb.GetNode(parallelize)})) + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parallelize), Child: physicalpb.GetNode(localTopK)})) + require.NoError(t, expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(localTopK), Child: physicalpb.GetNode(scan)})) } expected := PrintAsTree(&expectedPlan) diff --git a/pkg/engine/internal/planner/physical/parallelize.go b/pkg/engine/internal/planner/physical/parallelize.go deleted file mode 100644 index deb6b11359c8c..0000000000000 --- a/pkg/engine/internal/planner/physical/parallelize.go +++ /dev/null @@ -1,29 +0,0 @@ -package physical - -import "fmt" - -// Parallelize represents a hint to the engine to partition and parallelize the -// children branches of the Parallelize and emit results as a single sequence -// with no guaranteed order. -type Parallelize struct { - id string -} - -// ID returns a string that uniquely identifies the node in the plan. -func (p *Parallelize) ID() string { - if p.id == "" { - return fmt.Sprintf("%p", p) - } - return p.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (p *Parallelize) Clone() Node { - return &Parallelize{ /* nothing to clone */ } -} - -// Type returns [NodeTypeParallelize]. -func (p *Parallelize) Type() NodeType { return NodeTypeParallelize } - -// Accept implements the [Node] interface, dispatching itself to v. -func (p *Parallelize) Accept(v Visitor) error { return v.VisitParallelize(p) } diff --git a/pkg/engine/internal/planner/physical/parse.go b/pkg/engine/internal/planner/physical/parse.go deleted file mode 100644 index 9f2eb94263a69..0000000000000 --- a/pkg/engine/internal/planner/physical/parse.go +++ /dev/null @@ -1,60 +0,0 @@ -package physical - -import ( - "fmt" - "slices" -) - -// ParseNode represents a parsing operation in the physical plan. -// It extracts structured fields from log lines using the specified parser. -type ParseNode struct { - id string - Kind ParserKind - RequestedKeys []string -} - -// ParserKind represents the type of parser to use -type ParserKind int - -const ( - ParserInvalid ParserKind = iota - ParserLogfmt - ParserJSON -) - -func (p ParserKind) String() string { - switch p { - case ParserLogfmt: - return "logfmt" - case ParserJSON: - return "json" - default: - return "invalid" - } -} - -// ID returns a unique identifier for this ParseNode -func (n *ParseNode) ID() string { - if n.id != "" { - return n.id - } - return fmt.Sprintf("%p", n) -} - -// Clone returns a deep copy of the node (minus its ID). -func (n *ParseNode) Clone() Node { - return &ParseNode{ - Kind: n.Kind, - RequestedKeys: slices.Clone(n.RequestedKeys), - } -} - -// Type returns the node type -func (n *ParseNode) Type() NodeType { - return NodeTypeParse -} - -// Accept allows the ParseNode to be visited by a Visitor -func (n *ParseNode) Accept(v Visitor) error { - return v.VisitParse(n) -} diff --git a/pkg/engine/internal/planner/physical/physicalpb/expression.go b/pkg/engine/internal/planner/physical/physicalpb/expression.go new file mode 100644 index 0000000000000..501b248a79267 --- /dev/null +++ b/pkg/engine/internal/planner/physical/physicalpb/expression.go @@ -0,0 +1,83 @@ +package physicalpb + +import fmt "fmt" + +func (e *BinaryExpression) ToExpression() *Expression { + return &Expression{Kind: &Expression_BinaryExpression{BinaryExpression: e}} +} + +func (e *ColumnExpression) ToExpression() *Expression { + return &Expression{Kind: &Expression_ColumnExpression{ColumnExpression: e}} +} + +func (e *LiteralExpression) ToExpression() *Expression { + return &Expression{Kind: &Expression_LiteralExpression{LiteralExpression: e}} +} + +func (e *UnaryExpression) ToExpression() *Expression { + return &Expression{Kind: &Expression_UnaryExpression{UnaryExpression: e}} +} + +func cloneExpressions(exprs []*Expression) []*Expression { + clonedExprs := make([]*Expression, len(exprs)) + for i, expr := range exprs { + tmp := expr.Clone() + clonedExprs[i] = &tmp + } + return clonedExprs +} + +func cloneColExpressions(colExprs []*ColumnExpression) []*ColumnExpression { + clonedExprs := make([]*ColumnExpression, len(colExprs)) + for i, expr := range colExprs { + tmp := expr.Clone() + clonedExprs[i] = tmp.GetColumnExpression() + } + return clonedExprs +} + +func (e *Expression) Clone() Expression { + switch k := e.Kind.(type) { + case *Expression_UnaryExpression: + return k.UnaryExpression.Clone() + case *Expression_BinaryExpression: + return k.BinaryExpression.Clone() + case *Expression_LiteralExpression: + return k.LiteralExpression.Clone() + case *Expression_ColumnExpression: + return k.ColumnExpression.Clone() + default: + panic(fmt.Sprintf("unknown expression type %T", k)) + } +} + +// Clone returns a copy of the [UnaryExpr]. +func (e *UnaryExpression) Clone() Expression { + tmp := e.Value.Clone() + return *(&UnaryExpression{ + Value: &tmp, + Op: e.Op, + }).ToExpression() +} + +// Clone returns a copy of the [BinaryExpr]. +func (e *BinaryExpression) Clone() Expression { + tmpLeft := e.Left.Clone() + tmpRight := e.Right.Clone() + return *(&BinaryExpression{ + Left: &tmpLeft, + Right: &tmpRight, + Op: e.Op, + }).ToExpression() +} + +// Clone returns a copy of the [LiteralExpr]. +func (e *LiteralExpression) Clone() Expression { + // No need to clone literals. + return *(&LiteralExpression{Kind: e.Kind}).ToExpression() +} + +// Clone returns a copy of the [ColumnExpr]. +func (e *ColumnExpression) Clone() Expression { + return *(&ColumnExpression{Name: e.Name, Type: e.Type}).ToExpression() +} diff --git a/pkg/engine/internal/planner/physical/physicalpb/expression.pb.go b/pkg/engine/internal/planner/physical/physicalpb/expression.pb.go new file mode 100644 index 0000000000000..79356486b374d --- /dev/null +++ b/pkg/engine/internal/planner/physical/physicalpb/expression.pb.go @@ -0,0 +1,4757 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pkg/engine/internal/planner/physical/physicalpb/expression.proto + +package physicalpb + +import ( + encoding_binary "encoding/binary" + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" + reflect "reflect" + strconv "strconv" + strings "strings" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// UnaryOp denotes the kind of unary operation to perform. +type UnaryOp int32 + +const ( + UNARY_OP_INVALID UnaryOp = 0 + UNARY_OP_NOT UnaryOp = 1 + UNARY_OP_ABS UnaryOp = 2 + UNARY_OP_CAST_FLOAT UnaryOp = 3 + UNARY_OP_CAST_BYTES UnaryOp = 4 + UNARY_OP_CAST_DURATION UnaryOp = 5 +) + +var UnaryOp_name = map[int32]string{ + 0: "UNARY_OP_INVALID", + 1: "UNARY_OP_NOT", + 2: "UNARY_OP_ABS", + 3: "UNARY_OP_CAST_FLOAT", + 4: "UNARY_OP_CAST_BYTES", + 5: "UNARY_OP_CAST_DURATION", +} + +var UnaryOp_value = map[string]int32{ + "UNARY_OP_INVALID": 0, + "UNARY_OP_NOT": 1, + "UNARY_OP_ABS": 2, + "UNARY_OP_CAST_FLOAT": 3, + "UNARY_OP_CAST_BYTES": 4, + "UNARY_OP_CAST_DURATION": 5, +} + +func (UnaryOp) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{0} +} + +// BinaryOp denotes the kind of binary operation to perform. +type BinaryOp int32 + +const ( + BINARY_OP_INVALID BinaryOp = 0 + BINARY_OP_EQ BinaryOp = 1 + BINARY_OP_NEQ BinaryOp = 2 + BINARY_OP_GT BinaryOp = 3 + BINARY_OP_GTE BinaryOp = 4 + BINARY_OP_LT BinaryOp = 5 + BINARY_OP_LTE BinaryOp = 6 + BINARY_OP_AND BinaryOp = 7 + BINARY_OP_OR BinaryOp = 8 + BINARY_OP_XOR BinaryOp = 9 + BINARY_OP_NOT BinaryOp = 10 + BINARY_OP_ADD BinaryOp = 11 + BINARY_OP_SUB BinaryOp = 12 + BINARY_OP_MUL BinaryOp = 13 + BINARY_OP_DIV BinaryOp = 14 + BINARY_OP_MOD BinaryOp = 15 + BINARY_OP_POW BinaryOp = 16 + BINARY_OP_MATCH_SUBSTR BinaryOp = 17 + BINARY_OP_NOT_MATCH_SUBSTR BinaryOp = 18 + BINARY_OP_MATCH_RE BinaryOp = 19 + BINARY_OP_NOT_MATCH_RE BinaryOp = 20 + BINARY_OP_MATCH_PATTERN BinaryOp = 21 + BINARY_OP_NOT_MATCH_PATTERN BinaryOp = 22 +) + +var BinaryOp_name = map[int32]string{ + 0: "BINARY_OP_INVALID", + 1: "BINARY_OP_EQ", + 2: "BINARY_OP_NEQ", + 3: "BINARY_OP_GT", + 4: "BINARY_OP_GTE", + 5: "BINARY_OP_LT", + 6: "BINARY_OP_LTE", + 7: "BINARY_OP_AND", + 8: "BINARY_OP_OR", + 9: "BINARY_OP_XOR", + 10: "BINARY_OP_NOT", + 11: "BINARY_OP_ADD", + 12: "BINARY_OP_SUB", + 13: "BINARY_OP_MUL", + 14: "BINARY_OP_DIV", + 15: "BINARY_OP_MOD", + 16: "BINARY_OP_POW", + 17: "BINARY_OP_MATCH_SUBSTR", + 18: "BINARY_OP_NOT_MATCH_SUBSTR", + 19: "BINARY_OP_MATCH_RE", + 20: "BINARY_OP_NOT_MATCH_RE", + 21: "BINARY_OP_MATCH_PATTERN", + 22: "BINARY_OP_NOT_MATCH_PATTERN", +} + +var BinaryOp_value = map[string]int32{ + "BINARY_OP_INVALID": 0, + "BINARY_OP_EQ": 1, + "BINARY_OP_NEQ": 2, + "BINARY_OP_GT": 3, + "BINARY_OP_GTE": 4, + "BINARY_OP_LT": 5, + "BINARY_OP_LTE": 6, + "BINARY_OP_AND": 7, + "BINARY_OP_OR": 8, + "BINARY_OP_XOR": 9, + "BINARY_OP_NOT": 10, + "BINARY_OP_ADD": 11, + "BINARY_OP_SUB": 12, + "BINARY_OP_MUL": 13, + "BINARY_OP_DIV": 14, + "BINARY_OP_MOD": 15, + "BINARY_OP_POW": 16, + "BINARY_OP_MATCH_SUBSTR": 17, + "BINARY_OP_NOT_MATCH_SUBSTR": 18, + "BINARY_OP_MATCH_RE": 19, + "BINARY_OP_NOT_MATCH_RE": 20, + "BINARY_OP_MATCH_PATTERN": 21, + "BINARY_OP_NOT_MATCH_PATTERN": 22, +} + +func (BinaryOp) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{1} +} + +// ColumnType holds valid types of columns that can be referenced. +type ColumnType int32 + +const ( + COLUMN_TYPE_INVALID ColumnType = 0 + COLUMN_TYPE_BUILTIN ColumnType = 1 + COLUMN_TYPE_LABEL ColumnType = 2 + COLUMN_TYPE_METADATA ColumnType = 3 + COLUMN_TYPE_PARSED ColumnType = 4 + COLUMN_TYPE_AMBIGUOUS ColumnType = 5 + COLUMN_TYPE_GENERATED ColumnType = 6 +) + +var ColumnType_name = map[int32]string{ + 0: "COLUMN_TYPE_INVALID", + 1: "COLUMN_TYPE_BUILTIN", + 2: "COLUMN_TYPE_LABEL", + 3: "COLUMN_TYPE_METADATA", + 4: "COLUMN_TYPE_PARSED", + 5: "COLUMN_TYPE_AMBIGUOUS", + 6: "COLUMN_TYPE_GENERATED", +} + +var ColumnType_value = map[string]int32{ + "COLUMN_TYPE_INVALID": 0, + "COLUMN_TYPE_BUILTIN": 1, + "COLUMN_TYPE_LABEL": 2, + "COLUMN_TYPE_METADATA": 3, + "COLUMN_TYPE_PARSED": 4, + "COLUMN_TYPE_AMBIGUOUS": 5, + "COLUMN_TYPE_GENERATED": 6, +} + +func (ColumnType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{2} +} + +// Expression represents an expression used to compute values in output arrays. +type Expression struct { + // Types that are valid to be assigned to Kind: + // + // *Expression_UnaryExpression + // *Expression_BinaryExpression + // *Expression_LiteralExpression + // *Expression_ColumnExpression + Kind isExpression_Kind `protobuf_oneof:"kind"` +} + +func (m *Expression) Reset() { *m = Expression{} } +func (*Expression) ProtoMessage() {} +func (*Expression) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{0} +} +func (m *Expression) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Expression) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Expression.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Expression) XXX_Merge(src proto.Message) { + xxx_messageInfo_Expression.Merge(m, src) +} +func (m *Expression) XXX_Size() int { + return m.Size() +} +func (m *Expression) XXX_DiscardUnknown() { + xxx_messageInfo_Expression.DiscardUnknown(m) +} + +var xxx_messageInfo_Expression proto.InternalMessageInfo + +type isExpression_Kind interface { + isExpression_Kind() + Equal(interface{}) bool + MarshalTo([]byte) (int, error) + Size() int +} + +type Expression_UnaryExpression struct { + UnaryExpression *UnaryExpression `protobuf:"bytes,1,opt,name=unary_expression,json=unaryExpression,proto3,oneof"` +} +type Expression_BinaryExpression struct { + BinaryExpression *BinaryExpression `protobuf:"bytes,2,opt,name=binary_expression,json=binaryExpression,proto3,oneof"` +} +type Expression_LiteralExpression struct { + LiteralExpression *LiteralExpression `protobuf:"bytes,3,opt,name=literal_expression,json=literalExpression,proto3,oneof"` +} +type Expression_ColumnExpression struct { + ColumnExpression *ColumnExpression `protobuf:"bytes,4,opt,name=column_expression,json=columnExpression,proto3,oneof"` +} + +func (*Expression_UnaryExpression) isExpression_Kind() {} +func (*Expression_BinaryExpression) isExpression_Kind() {} +func (*Expression_LiteralExpression) isExpression_Kind() {} +func (*Expression_ColumnExpression) isExpression_Kind() {} + +func (m *Expression) GetKind() isExpression_Kind { + if m != nil { + return m.Kind + } + return nil +} + +func (m *Expression) GetUnaryExpression() *UnaryExpression { + if x, ok := m.GetKind().(*Expression_UnaryExpression); ok { + return x.UnaryExpression + } + return nil +} + +func (m *Expression) GetBinaryExpression() *BinaryExpression { + if x, ok := m.GetKind().(*Expression_BinaryExpression); ok { + return x.BinaryExpression + } + return nil +} + +func (m *Expression) GetLiteralExpression() *LiteralExpression { + if x, ok := m.GetKind().(*Expression_LiteralExpression); ok { + return x.LiteralExpression + } + return nil +} + +func (m *Expression) GetColumnExpression() *ColumnExpression { + if x, ok := m.GetKind().(*Expression_ColumnExpression); ok { + return x.ColumnExpression + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Expression) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Expression_UnaryExpression)(nil), + (*Expression_BinaryExpression)(nil), + (*Expression_LiteralExpression)(nil), + (*Expression_ColumnExpression)(nil), + } +} + +// UnaryExpression represents a unary operation applied to an expression. +type UnaryExpression struct { + Op UnaryOp `protobuf:"varint,1,opt,name=op,proto3,enum=physical.engine.loki.v1.UnaryOp" json:"op,omitempty"` + Value *Expression `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *UnaryExpression) Reset() { *m = UnaryExpression{} } +func (*UnaryExpression) ProtoMessage() {} +func (*UnaryExpression) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{1} +} +func (m *UnaryExpression) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UnaryExpression) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_UnaryExpression.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *UnaryExpression) XXX_Merge(src proto.Message) { + xxx_messageInfo_UnaryExpression.Merge(m, src) +} +func (m *UnaryExpression) XXX_Size() int { + return m.Size() +} +func (m *UnaryExpression) XXX_DiscardUnknown() { + xxx_messageInfo_UnaryExpression.DiscardUnknown(m) +} + +var xxx_messageInfo_UnaryExpression proto.InternalMessageInfo + +func (m *UnaryExpression) GetOp() UnaryOp { + if m != nil { + return m.Op + } + return UNARY_OP_INVALID +} + +func (m *UnaryExpression) GetValue() *Expression { + if m != nil { + return m.Value + } + return nil +} + +// BinaryExpression represents a binary operation applied to two expressions. +type BinaryExpression struct { + Op BinaryOp `protobuf:"varint,1,opt,name=op,proto3,enum=physical.engine.loki.v1.BinaryOp" json:"op,omitempty"` + Left *Expression `protobuf:"bytes,2,opt,name=left,proto3" json:"left,omitempty"` + Right *Expression `protobuf:"bytes,3,opt,name=right,proto3" json:"right,omitempty"` +} + +func (m *BinaryExpression) Reset() { *m = BinaryExpression{} } +func (*BinaryExpression) ProtoMessage() {} +func (*BinaryExpression) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{2} +} +func (m *BinaryExpression) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BinaryExpression) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BinaryExpression.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BinaryExpression) XXX_Merge(src proto.Message) { + xxx_messageInfo_BinaryExpression.Merge(m, src) +} +func (m *BinaryExpression) XXX_Size() int { + return m.Size() +} +func (m *BinaryExpression) XXX_DiscardUnknown() { + xxx_messageInfo_BinaryExpression.DiscardUnknown(m) +} + +var xxx_messageInfo_BinaryExpression proto.InternalMessageInfo + +func (m *BinaryExpression) GetOp() BinaryOp { + if m != nil { + return m.Op + } + return BINARY_OP_INVALID +} + +func (m *BinaryExpression) GetLeft() *Expression { + if m != nil { + return m.Left + } + return nil +} + +func (m *BinaryExpression) GetRight() *Expression { + if m != nil { + return m.Right + } + return nil +} + +// LiteralExpression represents a constant literal value in an expression tree. +type LiteralExpression struct { + // Types that are valid to be assigned to Kind: + // + // *LiteralExpression_NullLiteral + // *LiteralExpression_BoolLiteral + // *LiteralExpression_StringLiteral + // *LiteralExpression_IntegerLiteral + // *LiteralExpression_FloatLiteral + // *LiteralExpression_TimestampLiteral + // *LiteralExpression_DurationLiteral + // *LiteralExpression_BytesLiteral + Kind isLiteralExpression_Kind `protobuf_oneof:"kind"` +} + +func (m *LiteralExpression) Reset() { *m = LiteralExpression{} } +func (*LiteralExpression) ProtoMessage() {} +func (*LiteralExpression) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{3} +} +func (m *LiteralExpression) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LiteralExpression) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LiteralExpression.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *LiteralExpression) XXX_Merge(src proto.Message) { + xxx_messageInfo_LiteralExpression.Merge(m, src) +} +func (m *LiteralExpression) XXX_Size() int { + return m.Size() +} +func (m *LiteralExpression) XXX_DiscardUnknown() { + xxx_messageInfo_LiteralExpression.DiscardUnknown(m) +} + +var xxx_messageInfo_LiteralExpression proto.InternalMessageInfo + +type isLiteralExpression_Kind interface { + isLiteralExpression_Kind() + Equal(interface{}) bool + MarshalTo([]byte) (int, error) + Size() int +} + +type LiteralExpression_NullLiteral struct { + NullLiteral *NullLiteral `protobuf:"bytes,1,opt,name=null_literal,json=nullLiteral,proto3,oneof"` +} +type LiteralExpression_BoolLiteral struct { + BoolLiteral *BoolLiteral `protobuf:"bytes,2,opt,name=bool_literal,json=boolLiteral,proto3,oneof"` +} +type LiteralExpression_StringLiteral struct { + StringLiteral *StringLiteral `protobuf:"bytes,3,opt,name=string_literal,json=stringLiteral,proto3,oneof"` +} +type LiteralExpression_IntegerLiteral struct { + IntegerLiteral *IntegerLiteral `protobuf:"bytes,4,opt,name=integer_literal,json=integerLiteral,proto3,oneof"` +} +type LiteralExpression_FloatLiteral struct { + FloatLiteral *FloatLiteral `protobuf:"bytes,5,opt,name=float_literal,json=floatLiteral,proto3,oneof"` +} +type LiteralExpression_TimestampLiteral struct { + TimestampLiteral *TimestampLiteral `protobuf:"bytes,6,opt,name=timestamp_literal,json=timestampLiteral,proto3,oneof"` +} +type LiteralExpression_DurationLiteral struct { + DurationLiteral *DurationLiteral `protobuf:"bytes,7,opt,name=duration_literal,json=durationLiteral,proto3,oneof"` +} +type LiteralExpression_BytesLiteral struct { + BytesLiteral *BytesLiteral `protobuf:"bytes,8,opt,name=bytes_literal,json=bytesLiteral,proto3,oneof"` +} + +func (*LiteralExpression_NullLiteral) isLiteralExpression_Kind() {} +func (*LiteralExpression_BoolLiteral) isLiteralExpression_Kind() {} +func (*LiteralExpression_StringLiteral) isLiteralExpression_Kind() {} +func (*LiteralExpression_IntegerLiteral) isLiteralExpression_Kind() {} +func (*LiteralExpression_FloatLiteral) isLiteralExpression_Kind() {} +func (*LiteralExpression_TimestampLiteral) isLiteralExpression_Kind() {} +func (*LiteralExpression_DurationLiteral) isLiteralExpression_Kind() {} +func (*LiteralExpression_BytesLiteral) isLiteralExpression_Kind() {} + +func (m *LiteralExpression) GetKind() isLiteralExpression_Kind { + if m != nil { + return m.Kind + } + return nil +} + +func (m *LiteralExpression) GetNullLiteral() *NullLiteral { + if x, ok := m.GetKind().(*LiteralExpression_NullLiteral); ok { + return x.NullLiteral + } + return nil +} + +func (m *LiteralExpression) GetBoolLiteral() *BoolLiteral { + if x, ok := m.GetKind().(*LiteralExpression_BoolLiteral); ok { + return x.BoolLiteral + } + return nil +} + +func (m *LiteralExpression) GetStringLiteral() *StringLiteral { + if x, ok := m.GetKind().(*LiteralExpression_StringLiteral); ok { + return x.StringLiteral + } + return nil +} + +func (m *LiteralExpression) GetIntegerLiteral() *IntegerLiteral { + if x, ok := m.GetKind().(*LiteralExpression_IntegerLiteral); ok { + return x.IntegerLiteral + } + return nil +} + +func (m *LiteralExpression) GetFloatLiteral() *FloatLiteral { + if x, ok := m.GetKind().(*LiteralExpression_FloatLiteral); ok { + return x.FloatLiteral + } + return nil +} + +func (m *LiteralExpression) GetTimestampLiteral() *TimestampLiteral { + if x, ok := m.GetKind().(*LiteralExpression_TimestampLiteral); ok { + return x.TimestampLiteral + } + return nil +} + +func (m *LiteralExpression) GetDurationLiteral() *DurationLiteral { + if x, ok := m.GetKind().(*LiteralExpression_DurationLiteral); ok { + return x.DurationLiteral + } + return nil +} + +func (m *LiteralExpression) GetBytesLiteral() *BytesLiteral { + if x, ok := m.GetKind().(*LiteralExpression_BytesLiteral); ok { + return x.BytesLiteral + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*LiteralExpression) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*LiteralExpression_NullLiteral)(nil), + (*LiteralExpression_BoolLiteral)(nil), + (*LiteralExpression_StringLiteral)(nil), + (*LiteralExpression_IntegerLiteral)(nil), + (*LiteralExpression_FloatLiteral)(nil), + (*LiteralExpression_TimestampLiteral)(nil), + (*LiteralExpression_DurationLiteral)(nil), + (*LiteralExpression_BytesLiteral)(nil), + } +} + +// NullLiteral represents a null literal value. +type NullLiteral struct { +} + +func (m *NullLiteral) Reset() { *m = NullLiteral{} } +func (*NullLiteral) ProtoMessage() {} +func (*NullLiteral) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{4} +} +func (m *NullLiteral) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NullLiteral) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NullLiteral.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NullLiteral) XXX_Merge(src proto.Message) { + xxx_messageInfo_NullLiteral.Merge(m, src) +} +func (m *NullLiteral) XXX_Size() int { + return m.Size() +} +func (m *NullLiteral) XXX_DiscardUnknown() { + xxx_messageInfo_NullLiteral.DiscardUnknown(m) +} + +var xxx_messageInfo_NullLiteral proto.InternalMessageInfo + +// BoolLiteral represents a boolean literal value. +type BoolLiteral struct { + Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *BoolLiteral) Reset() { *m = BoolLiteral{} } +func (*BoolLiteral) ProtoMessage() {} +func (*BoolLiteral) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{5} +} +func (m *BoolLiteral) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BoolLiteral) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BoolLiteral.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BoolLiteral) XXX_Merge(src proto.Message) { + xxx_messageInfo_BoolLiteral.Merge(m, src) +} +func (m *BoolLiteral) XXX_Size() int { + return m.Size() +} +func (m *BoolLiteral) XXX_DiscardUnknown() { + xxx_messageInfo_BoolLiteral.DiscardUnknown(m) +} + +var xxx_messageInfo_BoolLiteral proto.InternalMessageInfo + +func (m *BoolLiteral) GetValue() bool { + if m != nil { + return m.Value + } + return false +} + +// StringLiteral represents a string literal value. +type StringLiteral struct { + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *StringLiteral) Reset() { *m = StringLiteral{} } +func (*StringLiteral) ProtoMessage() {} +func (*StringLiteral) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{6} +} +func (m *StringLiteral) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *StringLiteral) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_StringLiteral.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *StringLiteral) XXX_Merge(src proto.Message) { + xxx_messageInfo_StringLiteral.Merge(m, src) +} +func (m *StringLiteral) XXX_Size() int { + return m.Size() +} +func (m *StringLiteral) XXX_DiscardUnknown() { + xxx_messageInfo_StringLiteral.DiscardUnknown(m) +} + +var xxx_messageInfo_StringLiteral proto.InternalMessageInfo + +func (m *StringLiteral) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +// IntegerLiteral represents a signed integer literal value. +type IntegerLiteral struct { + Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *IntegerLiteral) Reset() { *m = IntegerLiteral{} } +func (*IntegerLiteral) ProtoMessage() {} +func (*IntegerLiteral) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{7} +} +func (m *IntegerLiteral) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *IntegerLiteral) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_IntegerLiteral.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *IntegerLiteral) XXX_Merge(src proto.Message) { + xxx_messageInfo_IntegerLiteral.Merge(m, src) +} +func (m *IntegerLiteral) XXX_Size() int { + return m.Size() +} +func (m *IntegerLiteral) XXX_DiscardUnknown() { + xxx_messageInfo_IntegerLiteral.DiscardUnknown(m) +} + +var xxx_messageInfo_IntegerLiteral proto.InternalMessageInfo + +func (m *IntegerLiteral) GetValue() int64 { + if m != nil { + return m.Value + } + return 0 +} + +// FloatLiteral represents a floating point literal value. +type FloatLiteral struct { + Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *FloatLiteral) Reset() { *m = FloatLiteral{} } +func (*FloatLiteral) ProtoMessage() {} +func (*FloatLiteral) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{8} +} +func (m *FloatLiteral) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FloatLiteral) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FloatLiteral.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *FloatLiteral) XXX_Merge(src proto.Message) { + xxx_messageInfo_FloatLiteral.Merge(m, src) +} +func (m *FloatLiteral) XXX_Size() int { + return m.Size() +} +func (m *FloatLiteral) XXX_DiscardUnknown() { + xxx_messageInfo_FloatLiteral.DiscardUnknown(m) +} + +var xxx_messageInfo_FloatLiteral proto.InternalMessageInfo + +func (m *FloatLiteral) GetValue() float64 { + if m != nil { + return m.Value + } + return 0 +} + +// TimestampLiteral represents a timestamp literal value in nanoseconds since +// the Unix epoch. +type TimestampLiteral struct { + Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *TimestampLiteral) Reset() { *m = TimestampLiteral{} } +func (*TimestampLiteral) ProtoMessage() {} +func (*TimestampLiteral) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{9} +} +func (m *TimestampLiteral) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TimestampLiteral) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TimestampLiteral.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TimestampLiteral) XXX_Merge(src proto.Message) { + xxx_messageInfo_TimestampLiteral.Merge(m, src) +} +func (m *TimestampLiteral) XXX_Size() int { + return m.Size() +} +func (m *TimestampLiteral) XXX_DiscardUnknown() { + xxx_messageInfo_TimestampLiteral.DiscardUnknown(m) +} + +var xxx_messageInfo_TimestampLiteral proto.InternalMessageInfo + +func (m *TimestampLiteral) GetValue() int64 { + if m != nil { + return m.Value + } + return 0 +} + +// DurationLiteral represents a duration literal value in nanoseconds. +type DurationLiteral struct { + Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *DurationLiteral) Reset() { *m = DurationLiteral{} } +func (*DurationLiteral) ProtoMessage() {} +func (*DurationLiteral) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{10} +} +func (m *DurationLiteral) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DurationLiteral) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DurationLiteral.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DurationLiteral) XXX_Merge(src proto.Message) { + xxx_messageInfo_DurationLiteral.Merge(m, src) +} +func (m *DurationLiteral) XXX_Size() int { + return m.Size() +} +func (m *DurationLiteral) XXX_DiscardUnknown() { + xxx_messageInfo_DurationLiteral.DiscardUnknown(m) +} + +var xxx_messageInfo_DurationLiteral proto.InternalMessageInfo + +func (m *DurationLiteral) GetValue() int64 { + if m != nil { + return m.Value + } + return 0 +} + +// BytesLiteral represents a bytes count literal value. +type BytesLiteral struct { + Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *BytesLiteral) Reset() { *m = BytesLiteral{} } +func (*BytesLiteral) ProtoMessage() {} +func (*BytesLiteral) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{11} +} +func (m *BytesLiteral) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BytesLiteral) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BytesLiteral.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BytesLiteral) XXX_Merge(src proto.Message) { + xxx_messageInfo_BytesLiteral.Merge(m, src) +} +func (m *BytesLiteral) XXX_Size() int { + return m.Size() +} +func (m *BytesLiteral) XXX_DiscardUnknown() { + xxx_messageInfo_BytesLiteral.DiscardUnknown(m) +} + +var xxx_messageInfo_BytesLiteral proto.InternalMessageInfo + +func (m *BytesLiteral) GetValue() int64 { + if m != nil { + return m.Value + } + return 0 +} + +// ColumnExpression is an expression used to reference a column. +type ColumnExpression struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Type ColumnType `protobuf:"varint,2,opt,name=type,proto3,enum=physical.engine.loki.v1.ColumnType" json:"type,omitempty"` +} + +func (m *ColumnExpression) Reset() { *m = ColumnExpression{} } +func (*ColumnExpression) ProtoMessage() {} +func (*ColumnExpression) Descriptor() ([]byte, []int) { + return fileDescriptor_14ac7d2685fb6178, []int{12} +} +func (m *ColumnExpression) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ColumnExpression) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ColumnExpression.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ColumnExpression) XXX_Merge(src proto.Message) { + xxx_messageInfo_ColumnExpression.Merge(m, src) +} +func (m *ColumnExpression) XXX_Size() int { + return m.Size() +} +func (m *ColumnExpression) XXX_DiscardUnknown() { + xxx_messageInfo_ColumnExpression.DiscardUnknown(m) +} + +var xxx_messageInfo_ColumnExpression proto.InternalMessageInfo + +func (m *ColumnExpression) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *ColumnExpression) GetType() ColumnType { + if m != nil { + return m.Type + } + return COLUMN_TYPE_INVALID +} + +func init() { + proto.RegisterEnum("physical.engine.loki.v1.UnaryOp", UnaryOp_name, UnaryOp_value) + proto.RegisterEnum("physical.engine.loki.v1.BinaryOp", BinaryOp_name, BinaryOp_value) + proto.RegisterEnum("physical.engine.loki.v1.ColumnType", ColumnType_name, ColumnType_value) + proto.RegisterType((*Expression)(nil), "physical.engine.loki.v1.Expression") + proto.RegisterType((*UnaryExpression)(nil), "physical.engine.loki.v1.UnaryExpression") + proto.RegisterType((*BinaryExpression)(nil), "physical.engine.loki.v1.BinaryExpression") + proto.RegisterType((*LiteralExpression)(nil), "physical.engine.loki.v1.LiteralExpression") + proto.RegisterType((*NullLiteral)(nil), "physical.engine.loki.v1.NullLiteral") + proto.RegisterType((*BoolLiteral)(nil), "physical.engine.loki.v1.BoolLiteral") + proto.RegisterType((*StringLiteral)(nil), "physical.engine.loki.v1.StringLiteral") + proto.RegisterType((*IntegerLiteral)(nil), "physical.engine.loki.v1.IntegerLiteral") + proto.RegisterType((*FloatLiteral)(nil), "physical.engine.loki.v1.FloatLiteral") + proto.RegisterType((*TimestampLiteral)(nil), "physical.engine.loki.v1.TimestampLiteral") + proto.RegisterType((*DurationLiteral)(nil), "physical.engine.loki.v1.DurationLiteral") + proto.RegisterType((*BytesLiteral)(nil), "physical.engine.loki.v1.BytesLiteral") + proto.RegisterType((*ColumnExpression)(nil), "physical.engine.loki.v1.ColumnExpression") +} + +func init() { + proto.RegisterFile("pkg/engine/internal/planner/physical/physicalpb/expression.proto", fileDescriptor_14ac7d2685fb6178) +} + +var fileDescriptor_14ac7d2685fb6178 = []byte{ + // 1032 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x96, 0xbd, 0x72, 0xdb, 0x46, + 0x10, 0xc7, 0x09, 0x8a, 0x94, 0xe4, 0x95, 0x48, 0x2e, 0xcf, 0xfa, 0x70, 0xec, 0x19, 0xc4, 0x91, + 0xbf, 0x14, 0x15, 0x64, 0x6c, 0x17, 0x99, 0x74, 0x01, 0x04, 0x58, 0x62, 0x06, 0x02, 0x64, 0x10, + 0x74, 0xac, 0xa4, 0xe0, 0x80, 0x12, 0x44, 0x61, 0x04, 0x01, 0x18, 0x10, 0xd4, 0x44, 0x4d, 0xc6, + 0x8f, 0x90, 0x3c, 0x43, 0x9a, 0xbc, 0x42, 0x8a, 0xf4, 0x29, 0x55, 0xba, 0x8c, 0xa8, 0x26, 0xa5, + 0xfb, 0xa4, 0xc8, 0x1c, 0x48, 0x02, 0x38, 0xc8, 0x30, 0xed, 0x8e, 0xf7, 0xbf, 0xff, 0xfe, 0xb0, + 0xb7, 0xb7, 0xb7, 0x43, 0xf8, 0xd6, 0x3f, 0xed, 0x37, 0x2d, 0xb7, 0x6f, 0xbb, 0x56, 0xd3, 0x76, + 0x43, 0x2b, 0x70, 0x4d, 0xa7, 0xe9, 0x3b, 0xa6, 0xeb, 0x5a, 0x41, 0xd3, 0x3f, 0xb9, 0x18, 0xd8, + 0x87, 0x54, 0x98, 0xfc, 0xf0, 0x7b, 0x4d, 0xeb, 0x27, 0x3f, 0xb0, 0x06, 0x03, 0xdb, 0x73, 0x1b, + 0x7e, 0xe0, 0x85, 0x1e, 0x59, 0x9f, 0x6e, 0x36, 0xc6, 0x98, 0x86, 0xe3, 0x9d, 0xda, 0x8d, 0xf3, + 0xa7, 0x1b, 0xff, 0x15, 0x01, 0xe4, 0xd8, 0x4d, 0x3a, 0x80, 0x43, 0xd7, 0x0c, 0x2e, 0xba, 0x09, + 0xe1, 0x0e, 0x77, 0x9f, 0xdb, 0x5c, 0x7a, 0xb6, 0xd9, 0xc8, 0x41, 0x34, 0x3a, 0x34, 0x20, 0x61, + 0xec, 0x16, 0xf4, 0xda, 0x90, 0x95, 0xc8, 0x6b, 0xa8, 0xf7, 0xec, 0x2c, 0xb7, 0x18, 0x71, 0xbf, + 0xcc, 0xe5, 0x8a, 0xf6, 0x0d, 0x30, 0xf6, 0x32, 0x1a, 0xf9, 0x11, 0x88, 0x63, 0x87, 0x56, 0x60, + 0x3a, 0x69, 0xf4, 0x5c, 0x84, 0xde, 0xca, 0x45, 0x2b, 0xe3, 0x10, 0x86, 0x5d, 0x77, 0xb2, 0x22, + 0x4d, 0xfb, 0xd0, 0x73, 0x86, 0x67, 0x6e, 0x9a, 0x5d, 0x9a, 0x91, 0xf6, 0x76, 0x14, 0xc1, 0xa6, + 0x7d, 0x98, 0xd1, 0xc4, 0x79, 0x28, 0x9d, 0xda, 0xee, 0xd1, 0xc6, 0xcf, 0x50, 0xcb, 0x94, 0x8f, + 0x7c, 0x05, 0x45, 0xcf, 0x8f, 0x8a, 0x5e, 0x7d, 0x76, 0xff, 0xc3, 0x45, 0xd7, 0x7c, 0xbd, 0xe8, + 0xf9, 0xe4, 0x1b, 0x28, 0x9f, 0x9b, 0xce, 0xd0, 0x9a, 0x54, 0xf4, 0x41, 0x6e, 0x50, 0xf2, 0x15, + 0x7d, 0x1c, 0xb1, 0xf1, 0x07, 0x07, 0x98, 0xad, 0x33, 0x79, 0x9a, 0xca, 0xe0, 0x8b, 0x19, 0xd7, + 0x33, 0x49, 0xe1, 0x6b, 0x28, 0x39, 0xd6, 0x71, 0xf8, 0x29, 0x19, 0x44, 0x01, 0x34, 0xf7, 0xc0, + 0xee, 0x9f, 0x84, 0x93, 0x2b, 0xfb, 0xb8, 0xdc, 0xa3, 0x88, 0x8d, 0xdf, 0xca, 0x50, 0xbf, 0x71, + 0x91, 0xa4, 0x05, 0xcb, 0xee, 0xd0, 0x71, 0xba, 0x93, 0xdb, 0x9c, 0x74, 0xef, 0xc3, 0x5c, 0xae, + 0x3a, 0x74, 0x9c, 0x09, 0x65, 0xb7, 0xa0, 0x2f, 0xb9, 0xc9, 0x92, 0xa2, 0x7a, 0x9e, 0x97, 0xa0, + 0x8a, 0x33, 0x50, 0xa2, 0xe7, 0xa5, 0x51, 0xbd, 0x64, 0x49, 0x34, 0xa8, 0x0e, 0xc2, 0xc0, 0x76, + 0xfb, 0x31, 0x6c, 0x7c, 0xde, 0xc7, 0xb9, 0xb0, 0x76, 0x64, 0x4f, 0x70, 0x95, 0x41, 0x5a, 0x20, + 0x3a, 0xd4, 0xe8, 0x24, 0xe8, 0x5b, 0x41, 0x4c, 0x1c, 0x37, 0xe6, 0x93, 0x5c, 0x62, 0x6b, 0xec, + 0x4f, 0x90, 0x55, 0x9b, 0x51, 0x88, 0x02, 0x95, 0x63, 0xc7, 0x33, 0xc3, 0x98, 0x58, 0x8e, 0x88, + 0x8f, 0x72, 0x89, 0x2f, 0xa8, 0x3b, 0xe1, 0x2d, 0x1f, 0xa7, 0xd6, 0xf4, 0xf1, 0x84, 0xf6, 0x99, + 0x35, 0x08, 0xcd, 0x33, 0x3f, 0x26, 0xce, 0xcf, 0x78, 0x3c, 0xc6, 0x34, 0x22, 0xa1, 0x62, 0x98, + 0xd1, 0xe8, 0x90, 0x3a, 0x1a, 0x06, 0x66, 0x68, 0x7b, 0x6e, 0x0c, 0x5e, 0x98, 0x31, 0xa4, 0xa4, + 0x49, 0x40, 0xc2, 0xad, 0x1d, 0xb1, 0x12, 0x3d, 0x7e, 0xef, 0x22, 0xb4, 0x06, 0x31, 0x73, 0x71, + 0xc6, 0xf1, 0x45, 0xea, 0x4e, 0x1d, 0xbf, 0x97, 0x5a, 0xc7, 0x2f, 0xbc, 0x02, 0x4b, 0xa9, 0x16, + 0xdb, 0x78, 0x00, 0x4b, 0xa9, 0x36, 0x21, 0x2b, 0xd3, 0xa7, 0x4b, 0xdb, 0x74, 0x71, 0xfa, 0x2a, + 0x1f, 0x41, 0x85, 0xb9, 0x7e, 0xd6, 0x76, 0x6b, 0x6a, 0x7b, 0x0c, 0x55, 0xf6, 0x4e, 0x59, 0xdf, + 0xdc, 0xd4, 0xf7, 0x10, 0x96, 0xd3, 0x37, 0xc5, 0xba, 0xb8, 0xa9, 0x6b, 0x13, 0x30, 0x5b, 0xfd, + 0x1c, 0xde, 0x13, 0xa8, 0x65, 0xca, 0x99, 0xff, 0xe1, 0x74, 0x8d, 0x72, 0x5c, 0x5d, 0xc0, 0xec, + 0xcc, 0x24, 0x04, 0x4a, 0xae, 0x79, 0x36, 0x3d, 0x6f, 0xf4, 0x9b, 0xce, 0x98, 0xf0, 0xc2, 0x1f, + 0x4f, 0xb9, 0xea, 0x07, 0x26, 0xc5, 0x18, 0x66, 0x5c, 0xf8, 0x96, 0x1e, 0x05, 0x6c, 0xfd, 0xca, + 0xc1, 0xc2, 0x64, 0x5e, 0x92, 0x15, 0xc0, 0x8e, 0x2a, 0xe8, 0x07, 0x5d, 0x6d, 0xbf, 0xdb, 0x52, + 0x5f, 0x09, 0x4a, 0x4b, 0xc2, 0x02, 0x41, 0x58, 0x8e, 0x55, 0x55, 0x33, 0x90, 0x63, 0x14, 0x41, + 0x6c, 0x63, 0x91, 0xac, 0xc3, 0xed, 0x58, 0xd9, 0x16, 0xda, 0x46, 0xf7, 0x85, 0xa2, 0x09, 0x06, + 0xce, 0xdd, 0xdc, 0x10, 0x0f, 0x0c, 0xb9, 0x8d, 0x25, 0x72, 0x17, 0xd6, 0xd8, 0x0d, 0xa9, 0xa3, + 0x0b, 0x46, 0x4b, 0x53, 0xb1, 0xbc, 0xf5, 0xef, 0x1c, 0x2c, 0x4e, 0x27, 0x28, 0x59, 0x85, 0xba, + 0xd8, 0x7a, 0x6f, 0x56, 0x89, 0x2c, 0xbf, 0x44, 0x8e, 0xd4, 0xa1, 0x92, 0x28, 0xaa, 0xfc, 0x12, + 0x8b, 0xac, 0x69, 0x87, 0xe6, 0xc3, 0x98, 0x76, 0x0c, 0x19, 0x4b, 0xac, 0x49, 0x31, 0xb0, 0xcc, + 0x9a, 0x14, 0x43, 0xc6, 0x79, 0x56, 0x12, 0x54, 0x09, 0x17, 0xd8, 0x38, 0x4d, 0xc7, 0x45, 0xd6, + 0xf4, 0x5a, 0xd3, 0xf1, 0x56, 0x26, 0x29, 0xcd, 0x40, 0xc8, 0xa0, 0x24, 0x09, 0x97, 0x58, 0xa9, + 0xdd, 0x11, 0x71, 0x99, 0x95, 0xf6, 0x3a, 0x0a, 0x56, 0x58, 0x49, 0x6a, 0xbd, 0xc2, 0x6a, 0xc6, + 0xa5, 0x49, 0x58, 0x63, 0xa5, 0x7d, 0xed, 0x7b, 0x44, 0x5a, 0xeb, 0x94, 0x4b, 0x30, 0xb6, 0x77, + 0xe9, 0x47, 0xda, 0x86, 0x8e, 0x75, 0xc2, 0xc3, 0x5d, 0x26, 0x41, 0x76, 0x9f, 0x90, 0x35, 0x20, + 0xd9, 0x58, 0x5d, 0xc6, 0xdb, 0x2c, 0x33, 0x89, 0xd3, 0x65, 0x5c, 0x21, 0xf7, 0x60, 0x3d, 0x1b, + 0xb3, 0x2f, 0x18, 0x86, 0xac, 0xab, 0xb8, 0x4a, 0x3e, 0x87, 0x7b, 0xef, 0x0b, 0x9c, 0x1a, 0xd6, + 0xb6, 0xfe, 0xe4, 0x00, 0x92, 0x36, 0xa5, 0x1d, 0xb4, 0xad, 0x29, 0x9d, 0x3d, 0xb5, 0x6b, 0x1c, + 0xec, 0xcb, 0xa9, 0x0e, 0xc8, 0x6c, 0x88, 0x9d, 0x96, 0x62, 0xb4, 0x54, 0xe4, 0x68, 0xc7, 0xa4, + 0x37, 0x14, 0x41, 0x94, 0x15, 0x2c, 0x92, 0x3b, 0xb0, 0x92, 0x96, 0xf7, 0x64, 0x43, 0x90, 0x04, + 0x43, 0xc0, 0x39, 0x7a, 0xc6, 0xf4, 0xce, 0xbe, 0xa0, 0xb7, 0x65, 0x09, 0x4b, 0xe4, 0x33, 0x58, + 0x4d, 0xeb, 0xc2, 0x9e, 0xd8, 0xda, 0xe9, 0x68, 0x9d, 0x36, 0x96, 0xb3, 0x5b, 0x3b, 0xb2, 0x2a, + 0xeb, 0x82, 0x21, 0x4b, 0x38, 0x2f, 0xbe, 0xe1, 0x2e, 0xaf, 0xf8, 0xc2, 0xdb, 0x2b, 0xbe, 0xf0, + 0xee, 0x8a, 0xe7, 0xde, 0x8c, 0x78, 0xee, 0xf7, 0x11, 0xcf, 0xfd, 0x35, 0xe2, 0xb9, 0xcb, 0x11, + 0xcf, 0xfd, 0x3d, 0xe2, 0xb9, 0x7f, 0x46, 0x7c, 0xe1, 0xdd, 0x88, 0xe7, 0x7e, 0xb9, 0xe6, 0x0b, + 0x97, 0xd7, 0x7c, 0xe1, 0xed, 0x35, 0x5f, 0xf8, 0xe1, 0xbb, 0xbe, 0x1d, 0x9e, 0x0c, 0x7b, 0x8d, + 0x43, 0xef, 0xac, 0xd9, 0x0f, 0xcc, 0x63, 0xd3, 0x35, 0x9b, 0xf4, 0xd5, 0x36, 0xcf, 0x9f, 0x37, + 0x3f, 0xf1, 0x2f, 0x6e, 0x6f, 0x3e, 0xfa, 0x63, 0xfb, 0xfc, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x6f, 0xb3, 0x34, 0x12, 0x1c, 0x0b, 0x00, 0x00, +} + +func (x UnaryOp) String() string { + s, ok := UnaryOp_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (x BinaryOp) String() string { + s, ok := BinaryOp_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (x ColumnType) String() string { + s, ok := ColumnType_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (this *Expression) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Expression) + if !ok { + that2, ok := that.(Expression) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if that1.Kind == nil { + if this.Kind != nil { + return false + } + } else if this.Kind == nil { + return false + } else if !this.Kind.Equal(that1.Kind) { + return false + } + return true +} +func (this *Expression_UnaryExpression) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Expression_UnaryExpression) + if !ok { + that2, ok := that.(Expression_UnaryExpression) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.UnaryExpression.Equal(that1.UnaryExpression) { + return false + } + return true +} +func (this *Expression_BinaryExpression) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Expression_BinaryExpression) + if !ok { + that2, ok := that.(Expression_BinaryExpression) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.BinaryExpression.Equal(that1.BinaryExpression) { + return false + } + return true +} +func (this *Expression_LiteralExpression) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Expression_LiteralExpression) + if !ok { + that2, ok := that.(Expression_LiteralExpression) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.LiteralExpression.Equal(that1.LiteralExpression) { + return false + } + return true +} +func (this *Expression_ColumnExpression) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Expression_ColumnExpression) + if !ok { + that2, ok := that.(Expression_ColumnExpression) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.ColumnExpression.Equal(that1.ColumnExpression) { + return false + } + return true +} +func (this *UnaryExpression) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*UnaryExpression) + if !ok { + that2, ok := that.(UnaryExpression) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Op != that1.Op { + return false + } + if !this.Value.Equal(that1.Value) { + return false + } + return true +} +func (this *BinaryExpression) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*BinaryExpression) + if !ok { + that2, ok := that.(BinaryExpression) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Op != that1.Op { + return false + } + if !this.Left.Equal(that1.Left) { + return false + } + if !this.Right.Equal(that1.Right) { + return false + } + return true +} +func (this *LiteralExpression) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*LiteralExpression) + if !ok { + that2, ok := that.(LiteralExpression) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if that1.Kind == nil { + if this.Kind != nil { + return false + } + } else if this.Kind == nil { + return false + } else if !this.Kind.Equal(that1.Kind) { + return false + } + return true +} +func (this *LiteralExpression_NullLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*LiteralExpression_NullLiteral) + if !ok { + that2, ok := that.(LiteralExpression_NullLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.NullLiteral.Equal(that1.NullLiteral) { + return false + } + return true +} +func (this *LiteralExpression_BoolLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*LiteralExpression_BoolLiteral) + if !ok { + that2, ok := that.(LiteralExpression_BoolLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.BoolLiteral.Equal(that1.BoolLiteral) { + return false + } + return true +} +func (this *LiteralExpression_StringLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*LiteralExpression_StringLiteral) + if !ok { + that2, ok := that.(LiteralExpression_StringLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.StringLiteral.Equal(that1.StringLiteral) { + return false + } + return true +} +func (this *LiteralExpression_IntegerLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*LiteralExpression_IntegerLiteral) + if !ok { + that2, ok := that.(LiteralExpression_IntegerLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.IntegerLiteral.Equal(that1.IntegerLiteral) { + return false + } + return true +} +func (this *LiteralExpression_FloatLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*LiteralExpression_FloatLiteral) + if !ok { + that2, ok := that.(LiteralExpression_FloatLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.FloatLiteral.Equal(that1.FloatLiteral) { + return false + } + return true +} +func (this *LiteralExpression_TimestampLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*LiteralExpression_TimestampLiteral) + if !ok { + that2, ok := that.(LiteralExpression_TimestampLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.TimestampLiteral.Equal(that1.TimestampLiteral) { + return false + } + return true +} +func (this *LiteralExpression_DurationLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*LiteralExpression_DurationLiteral) + if !ok { + that2, ok := that.(LiteralExpression_DurationLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.DurationLiteral.Equal(that1.DurationLiteral) { + return false + } + return true +} +func (this *LiteralExpression_BytesLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*LiteralExpression_BytesLiteral) + if !ok { + that2, ok := that.(LiteralExpression_BytesLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.BytesLiteral.Equal(that1.BytesLiteral) { + return false + } + return true +} +func (this *NullLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*NullLiteral) + if !ok { + that2, ok := that.(NullLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (this *BoolLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*BoolLiteral) + if !ok { + that2, ok := that.(BoolLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Value != that1.Value { + return false + } + return true +} +func (this *StringLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*StringLiteral) + if !ok { + that2, ok := that.(StringLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Value != that1.Value { + return false + } + return true +} +func (this *IntegerLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*IntegerLiteral) + if !ok { + that2, ok := that.(IntegerLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Value != that1.Value { + return false + } + return true +} +func (this *FloatLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*FloatLiteral) + if !ok { + that2, ok := that.(FloatLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Value != that1.Value { + return false + } + return true +} +func (this *TimestampLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*TimestampLiteral) + if !ok { + that2, ok := that.(TimestampLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Value != that1.Value { + return false + } + return true +} +func (this *DurationLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*DurationLiteral) + if !ok { + that2, ok := that.(DurationLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Value != that1.Value { + return false + } + return true +} +func (this *BytesLiteral) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*BytesLiteral) + if !ok { + that2, ok := that.(BytesLiteral) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Value != that1.Value { + return false + } + return true +} +func (this *ColumnExpression) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ColumnExpression) + if !ok { + that2, ok := that.(ColumnExpression) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Name != that1.Name { + return false + } + if this.Type != that1.Type { + return false + } + return true +} +func (this *Expression) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 8) + s = append(s, "&physicalpb.Expression{") + if this.Kind != nil { + s = append(s, "Kind: "+fmt.Sprintf("%#v", this.Kind)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Expression_UnaryExpression) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.Expression_UnaryExpression{` + + `UnaryExpression:` + fmt.Sprintf("%#v", this.UnaryExpression) + `}`}, ", ") + return s +} +func (this *Expression_BinaryExpression) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.Expression_BinaryExpression{` + + `BinaryExpression:` + fmt.Sprintf("%#v", this.BinaryExpression) + `}`}, ", ") + return s +} +func (this *Expression_LiteralExpression) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.Expression_LiteralExpression{` + + `LiteralExpression:` + fmt.Sprintf("%#v", this.LiteralExpression) + `}`}, ", ") + return s +} +func (this *Expression_ColumnExpression) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.Expression_ColumnExpression{` + + `ColumnExpression:` + fmt.Sprintf("%#v", this.ColumnExpression) + `}`}, ", ") + return s +} +func (this *UnaryExpression) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&physicalpb.UnaryExpression{") + s = append(s, "Op: "+fmt.Sprintf("%#v", this.Op)+",\n") + if this.Value != nil { + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *BinaryExpression) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 7) + s = append(s, "&physicalpb.BinaryExpression{") + s = append(s, "Op: "+fmt.Sprintf("%#v", this.Op)+",\n") + if this.Left != nil { + s = append(s, "Left: "+fmt.Sprintf("%#v", this.Left)+",\n") + } + if this.Right != nil { + s = append(s, "Right: "+fmt.Sprintf("%#v", this.Right)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *LiteralExpression) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 12) + s = append(s, "&physicalpb.LiteralExpression{") + if this.Kind != nil { + s = append(s, "Kind: "+fmt.Sprintf("%#v", this.Kind)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *LiteralExpression_NullLiteral) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.LiteralExpression_NullLiteral{` + + `NullLiteral:` + fmt.Sprintf("%#v", this.NullLiteral) + `}`}, ", ") + return s +} +func (this *LiteralExpression_BoolLiteral) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.LiteralExpression_BoolLiteral{` + + `BoolLiteral:` + fmt.Sprintf("%#v", this.BoolLiteral) + `}`}, ", ") + return s +} +func (this *LiteralExpression_StringLiteral) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.LiteralExpression_StringLiteral{` + + `StringLiteral:` + fmt.Sprintf("%#v", this.StringLiteral) + `}`}, ", ") + return s +} +func (this *LiteralExpression_IntegerLiteral) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.LiteralExpression_IntegerLiteral{` + + `IntegerLiteral:` + fmt.Sprintf("%#v", this.IntegerLiteral) + `}`}, ", ") + return s +} +func (this *LiteralExpression_FloatLiteral) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.LiteralExpression_FloatLiteral{` + + `FloatLiteral:` + fmt.Sprintf("%#v", this.FloatLiteral) + `}`}, ", ") + return s +} +func (this *LiteralExpression_TimestampLiteral) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.LiteralExpression_TimestampLiteral{` + + `TimestampLiteral:` + fmt.Sprintf("%#v", this.TimestampLiteral) + `}`}, ", ") + return s +} +func (this *LiteralExpression_DurationLiteral) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.LiteralExpression_DurationLiteral{` + + `DurationLiteral:` + fmt.Sprintf("%#v", this.DurationLiteral) + `}`}, ", ") + return s +} +func (this *LiteralExpression_BytesLiteral) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.LiteralExpression_BytesLiteral{` + + `BytesLiteral:` + fmt.Sprintf("%#v", this.BytesLiteral) + `}`}, ", ") + return s +} +func (this *NullLiteral) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 4) + s = append(s, "&physicalpb.NullLiteral{") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *BoolLiteral) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.BoolLiteral{") + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *StringLiteral) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.StringLiteral{") + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *IntegerLiteral) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.IntegerLiteral{") + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *FloatLiteral) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.FloatLiteral{") + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *TimestampLiteral) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.TimestampLiteral{") + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *DurationLiteral) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.DurationLiteral{") + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *BytesLiteral) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.BytesLiteral{") + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *ColumnExpression) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&physicalpb.ColumnExpression{") + s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n") + s = append(s, "Type: "+fmt.Sprintf("%#v", this.Type)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func valueToGoStringExpression(v interface{}, typ string) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) +} +func (m *Expression) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Expression) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Expression) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Kind != nil { + { + size := m.Kind.Size() + i -= size + if _, err := m.Kind.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Expression_UnaryExpression) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *Expression_UnaryExpression) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.UnaryExpression != nil { + { + size, err := m.UnaryExpression.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Expression_BinaryExpression) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *Expression_BinaryExpression) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.BinaryExpression != nil { + { + size, err := m.BinaryExpression.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Expression_LiteralExpression) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *Expression_LiteralExpression) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LiteralExpression != nil { + { + size, err := m.LiteralExpression.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Expression_ColumnExpression) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *Expression_ColumnExpression) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ColumnExpression != nil { + { + size, err := m.ColumnExpression.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *UnaryExpression) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UnaryExpression) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UnaryExpression) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != nil { + { + size, err := m.Value.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Op != 0 { + i = encodeVarintExpression(dAtA, i, uint64(m.Op)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *BinaryExpression) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BinaryExpression) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BinaryExpression) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Right != nil { + { + size, err := m.Right.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Left != nil { + { + size, err := m.Left.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Op != 0 { + i = encodeVarintExpression(dAtA, i, uint64(m.Op)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *LiteralExpression) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LiteralExpression) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LiteralExpression) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Kind != nil { + { + size := m.Kind.Size() + i -= size + if _, err := m.Kind.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *LiteralExpression_NullLiteral) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *LiteralExpression_NullLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.NullLiteral != nil { + { + size, err := m.NullLiteral.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *LiteralExpression_BoolLiteral) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *LiteralExpression_BoolLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.BoolLiteral != nil { + { + size, err := m.BoolLiteral.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *LiteralExpression_StringLiteral) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *LiteralExpression_StringLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.StringLiteral != nil { + { + size, err := m.StringLiteral.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *LiteralExpression_IntegerLiteral) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *LiteralExpression_IntegerLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.IntegerLiteral != nil { + { + size, err := m.IntegerLiteral.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *LiteralExpression_FloatLiteral) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *LiteralExpression_FloatLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.FloatLiteral != nil { + { + size, err := m.FloatLiteral.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *LiteralExpression_TimestampLiteral) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *LiteralExpression_TimestampLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.TimestampLiteral != nil { + { + size, err := m.TimestampLiteral.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *LiteralExpression_DurationLiteral) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *LiteralExpression_DurationLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.DurationLiteral != nil { + { + size, err := m.DurationLiteral.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *LiteralExpression_BytesLiteral) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *LiteralExpression_BytesLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.BytesLiteral != nil { + { + size, err := m.BytesLiteral.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExpression(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *NullLiteral) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NullLiteral) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NullLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *BoolLiteral) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BoolLiteral) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BoolLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value { + i-- + if m.Value { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *StringLiteral) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *StringLiteral) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StringLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Value) > 0 { + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarintExpression(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *IntegerLiteral) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *IntegerLiteral) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *IntegerLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != 0 { + i = encodeVarintExpression(dAtA, i, uint64(m.Value)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *FloatLiteral) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *FloatLiteral) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FloatLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != 0 { + i -= 8 + encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value)))) + i-- + dAtA[i] = 0x9 + } + return len(dAtA) - i, nil +} + +func (m *TimestampLiteral) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TimestampLiteral) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TimestampLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != 0 { + i = encodeVarintExpression(dAtA, i, uint64(m.Value)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *DurationLiteral) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DurationLiteral) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DurationLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != 0 { + i = encodeVarintExpression(dAtA, i, uint64(m.Value)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *BytesLiteral) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BytesLiteral) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BytesLiteral) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != 0 { + i = encodeVarintExpression(dAtA, i, uint64(m.Value)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ColumnExpression) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ColumnExpression) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ColumnExpression) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Type != 0 { + i = encodeVarintExpression(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x10 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintExpression(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintExpression(dAtA []byte, offset int, v uint64) int { + offset -= sovExpression(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Expression) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Kind != nil { + n += m.Kind.Size() + } + return n +} + +func (m *Expression_UnaryExpression) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.UnaryExpression != nil { + l = m.UnaryExpression.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *Expression_BinaryExpression) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BinaryExpression != nil { + l = m.BinaryExpression.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *Expression_LiteralExpression) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LiteralExpression != nil { + l = m.LiteralExpression.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *Expression_ColumnExpression) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ColumnExpression != nil { + l = m.ColumnExpression.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *UnaryExpression) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Op != 0 { + n += 1 + sovExpression(uint64(m.Op)) + } + if m.Value != nil { + l = m.Value.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} + +func (m *BinaryExpression) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Op != 0 { + n += 1 + sovExpression(uint64(m.Op)) + } + if m.Left != nil { + l = m.Left.Size() + n += 1 + l + sovExpression(uint64(l)) + } + if m.Right != nil { + l = m.Right.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} + +func (m *LiteralExpression) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Kind != nil { + n += m.Kind.Size() + } + return n +} + +func (m *LiteralExpression_NullLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.NullLiteral != nil { + l = m.NullLiteral.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *LiteralExpression_BoolLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BoolLiteral != nil { + l = m.BoolLiteral.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *LiteralExpression_StringLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.StringLiteral != nil { + l = m.StringLiteral.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *LiteralExpression_IntegerLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.IntegerLiteral != nil { + l = m.IntegerLiteral.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *LiteralExpression_FloatLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.FloatLiteral != nil { + l = m.FloatLiteral.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *LiteralExpression_TimestampLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.TimestampLiteral != nil { + l = m.TimestampLiteral.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *LiteralExpression_DurationLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DurationLiteral != nil { + l = m.DurationLiteral.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *LiteralExpression_BytesLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BytesLiteral != nil { + l = m.BytesLiteral.Size() + n += 1 + l + sovExpression(uint64(l)) + } + return n +} +func (m *NullLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *BoolLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value { + n += 2 + } + return n +} + +func (m *StringLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Value) + if l > 0 { + n += 1 + l + sovExpression(uint64(l)) + } + return n +} + +func (m *IntegerLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != 0 { + n += 1 + sovExpression(uint64(m.Value)) + } + return n +} + +func (m *FloatLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != 0 { + n += 9 + } + return n +} + +func (m *TimestampLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != 0 { + n += 1 + sovExpression(uint64(m.Value)) + } + return n +} + +func (m *DurationLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != 0 { + n += 1 + sovExpression(uint64(m.Value)) + } + return n +} + +func (m *BytesLiteral) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != 0 { + n += 1 + sovExpression(uint64(m.Value)) + } + return n +} + +func (m *ColumnExpression) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sovExpression(uint64(l)) + } + if m.Type != 0 { + n += 1 + sovExpression(uint64(m.Type)) + } + return n +} + +func sovExpression(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozExpression(x uint64) (n int) { + return sovExpression(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *Expression) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Expression{`, + `Kind:` + fmt.Sprintf("%v", this.Kind) + `,`, + `}`, + }, "") + return s +} +func (this *Expression_UnaryExpression) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Expression_UnaryExpression{`, + `UnaryExpression:` + strings.Replace(fmt.Sprintf("%v", this.UnaryExpression), "UnaryExpression", "UnaryExpression", 1) + `,`, + `}`, + }, "") + return s +} +func (this *Expression_BinaryExpression) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Expression_BinaryExpression{`, + `BinaryExpression:` + strings.Replace(fmt.Sprintf("%v", this.BinaryExpression), "BinaryExpression", "BinaryExpression", 1) + `,`, + `}`, + }, "") + return s +} +func (this *Expression_LiteralExpression) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Expression_LiteralExpression{`, + `LiteralExpression:` + strings.Replace(fmt.Sprintf("%v", this.LiteralExpression), "LiteralExpression", "LiteralExpression", 1) + `,`, + `}`, + }, "") + return s +} +func (this *Expression_ColumnExpression) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Expression_ColumnExpression{`, + `ColumnExpression:` + strings.Replace(fmt.Sprintf("%v", this.ColumnExpression), "ColumnExpression", "ColumnExpression", 1) + `,`, + `}`, + }, "") + return s +} +func (this *UnaryExpression) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&UnaryExpression{`, + `Op:` + fmt.Sprintf("%v", this.Op) + `,`, + `Value:` + strings.Replace(this.Value.String(), "Expression", "Expression", 1) + `,`, + `}`, + }, "") + return s +} +func (this *BinaryExpression) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&BinaryExpression{`, + `Op:` + fmt.Sprintf("%v", this.Op) + `,`, + `Left:` + strings.Replace(this.Left.String(), "Expression", "Expression", 1) + `,`, + `Right:` + strings.Replace(this.Right.String(), "Expression", "Expression", 1) + `,`, + `}`, + }, "") + return s +} +func (this *LiteralExpression) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LiteralExpression{`, + `Kind:` + fmt.Sprintf("%v", this.Kind) + `,`, + `}`, + }, "") + return s +} +func (this *LiteralExpression_NullLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LiteralExpression_NullLiteral{`, + `NullLiteral:` + strings.Replace(fmt.Sprintf("%v", this.NullLiteral), "NullLiteral", "NullLiteral", 1) + `,`, + `}`, + }, "") + return s +} +func (this *LiteralExpression_BoolLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LiteralExpression_BoolLiteral{`, + `BoolLiteral:` + strings.Replace(fmt.Sprintf("%v", this.BoolLiteral), "BoolLiteral", "BoolLiteral", 1) + `,`, + `}`, + }, "") + return s +} +func (this *LiteralExpression_StringLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LiteralExpression_StringLiteral{`, + `StringLiteral:` + strings.Replace(fmt.Sprintf("%v", this.StringLiteral), "StringLiteral", "StringLiteral", 1) + `,`, + `}`, + }, "") + return s +} +func (this *LiteralExpression_IntegerLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LiteralExpression_IntegerLiteral{`, + `IntegerLiteral:` + strings.Replace(fmt.Sprintf("%v", this.IntegerLiteral), "IntegerLiteral", "IntegerLiteral", 1) + `,`, + `}`, + }, "") + return s +} +func (this *LiteralExpression_FloatLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LiteralExpression_FloatLiteral{`, + `FloatLiteral:` + strings.Replace(fmt.Sprintf("%v", this.FloatLiteral), "FloatLiteral", "FloatLiteral", 1) + `,`, + `}`, + }, "") + return s +} +func (this *LiteralExpression_TimestampLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LiteralExpression_TimestampLiteral{`, + `TimestampLiteral:` + strings.Replace(fmt.Sprintf("%v", this.TimestampLiteral), "TimestampLiteral", "TimestampLiteral", 1) + `,`, + `}`, + }, "") + return s +} +func (this *LiteralExpression_DurationLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LiteralExpression_DurationLiteral{`, + `DurationLiteral:` + strings.Replace(fmt.Sprintf("%v", this.DurationLiteral), "DurationLiteral", "DurationLiteral", 1) + `,`, + `}`, + }, "") + return s +} +func (this *LiteralExpression_BytesLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LiteralExpression_BytesLiteral{`, + `BytesLiteral:` + strings.Replace(fmt.Sprintf("%v", this.BytesLiteral), "BytesLiteral", "BytesLiteral", 1) + `,`, + `}`, + }, "") + return s +} +func (this *NullLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&NullLiteral{`, + `}`, + }, "") + return s +} +func (this *BoolLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&BoolLiteral{`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} +func (this *StringLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&StringLiteral{`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} +func (this *IntegerLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&IntegerLiteral{`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} +func (this *FloatLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&FloatLiteral{`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} +func (this *TimestampLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&TimestampLiteral{`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} +func (this *DurationLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&DurationLiteral{`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} +func (this *BytesLiteral) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&BytesLiteral{`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} +func (this *ColumnExpression) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ColumnExpression{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `}`, + }, "") + return s +} +func valueToStringExpression(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *Expression) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Expression: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Expression: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UnaryExpression", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &UnaryExpression{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &Expression_UnaryExpression{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BinaryExpression", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &BinaryExpression{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &Expression_BinaryExpression{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LiteralExpression", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &LiteralExpression{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &Expression_LiteralExpression{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ColumnExpression", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ColumnExpression{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &Expression_ColumnExpression{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *UnaryExpression) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UnaryExpression: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UnaryExpression: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Op", wireType) + } + m.Op = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Op |= UnaryOp(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Value == nil { + m.Value = &Expression{} + } + if err := m.Value.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BinaryExpression) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BinaryExpression: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BinaryExpression: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Op", wireType) + } + m.Op = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Op |= BinaryOp(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Left", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Left == nil { + m.Left = &Expression{} + } + if err := m.Left.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Right", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Right == nil { + m.Right = &Expression{} + } + if err := m.Right.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LiteralExpression) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LiteralExpression: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LiteralExpression: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NullLiteral", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &NullLiteral{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &LiteralExpression_NullLiteral{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BoolLiteral", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &BoolLiteral{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &LiteralExpression_BoolLiteral{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StringLiteral", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &StringLiteral{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &LiteralExpression_StringLiteral{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IntegerLiteral", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &IntegerLiteral{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &LiteralExpression_IntegerLiteral{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FloatLiteral", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &FloatLiteral{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &LiteralExpression_FloatLiteral{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimestampLiteral", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &TimestampLiteral{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &LiteralExpression_TimestampLiteral{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DurationLiteral", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &DurationLiteral{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &LiteralExpression_DurationLiteral{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BytesLiteral", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &BytesLiteral{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &LiteralExpression_BytesLiteral{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NullLiteral) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NullLiteral: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NullLiteral: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BoolLiteral) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BoolLiteral: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BoolLiteral: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Value = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *StringLiteral) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: StringLiteral: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StringLiteral: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *IntegerLiteral) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: IntegerLiteral: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: IntegerLiteral: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + m.Value = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Value |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *FloatLiteral) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: FloatLiteral: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FloatLiteral: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var v uint64 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + m.Value = float64(math.Float64frombits(v)) + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TimestampLiteral) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TimestampLiteral: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TimestampLiteral: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + m.Value = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Value |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DurationLiteral) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DurationLiteral: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DurationLiteral: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + m.Value = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Value |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BytesLiteral) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BytesLiteral: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BytesLiteral: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + m.Value = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Value |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ColumnExpression) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ColumnExpression: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ColumnExpression: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthExpression + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthExpression + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExpression + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= ColumnType(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipExpression(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthExpression + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipExpression(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowExpression + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowExpression + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowExpression + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthExpression + } + iNdEx += length + if iNdEx < 0 { + return 0, ErrInvalidLengthExpression + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowExpression + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipExpression(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + if iNdEx < 0 { + return 0, ErrInvalidLengthExpression + } + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthExpression = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowExpression = fmt.Errorf("proto: integer overflow") +) diff --git a/pkg/engine/internal/planner/physical/physicalpb/expression.proto b/pkg/engine/internal/planner/physical/physicalpb/expression.proto new file mode 100644 index 0000000000000..86470986df2ee --- /dev/null +++ b/pkg/engine/internal/planner/physical/physicalpb/expression.proto @@ -0,0 +1,140 @@ +syntax = "proto3"; + +package physical.engine.loki.v1; + +option go_package = "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb"; + +// Expression represents an expression used to compute values in output arrays. +message Expression { + oneof kind { + UnaryExpression unary_expression = 1; + BinaryExpression binary_expression = 2; + LiteralExpression literal_expression = 3; + ColumnExpression column_expression = 4; + } +} + +// UnaryExpression represents a unary operation applied to an expression. +message UnaryExpression { + UnaryOp op = 1; + Expression value = 2; +} + +// UnaryOp denotes the kind of unary operation to perform. +enum UnaryOp { + UNARY_OP_INVALID = 0; // Invalid unary operation. + UNARY_OP_NOT = 1; // Logical NOT operation (!). + UNARY_OP_ABS = 2; // Mathematical absolute operation (abs). + UNARY_OP_CAST_FLOAT = 3; // Cast string to float value operation (unwrap). + UNARY_OP_CAST_BYTES = 4; // Cast string bytes to float value operation (unwrap). + UNARY_OP_CAST_DURATION = 5; // Cast string duration to float value operation (unwrap). +} + +// BinaryExpression represents a binary operation applied to two expressions. +message BinaryExpression { + BinaryOp op = 1; + Expression left = 2; + Expression right = 3; +} + +// BinaryOp denotes the kind of binary operation to perform. +enum BinaryOp { + BINARY_OP_INVALID = 0; // Invalid binary operation. + + BINARY_OP_EQ = 1; // Equality comparison (==). + BINARY_OP_NEQ = 2; // Inequality comparison (!=). + BINARY_OP_GT = 3; // Greater than comparison (>). + BINARY_OP_GTE = 4; // Greater than or equal comparison (>=). + BINARY_OP_LT = 5; // Less than comparison (<). + BINARY_OP_LTE = 6; // Less than or equal comparison (<=). + + BINARY_OP_AND = 7; // Logical AND operation (&&). + BINARY_OP_OR = 8; // Logical OR operation (||). + BINARY_OP_XOR = 9; // Logical XOR operation (^). + BINARY_OP_NOT = 10; // Logical NOT operation (!). + + BINARY_OP_ADD = 11; // Addition operation (+). + BINARY_OP_SUB = 12; // Subtraction operation (-). + BINARY_OP_MUL = 13; // Multiplication operation (*). + BINARY_OP_DIV = 14; // Division operation (/). + BINARY_OP_MOD = 15; // Modulo operation (%). + BINARY_OP_POW = 16; // power/exponentiation operation (^). + + BINARY_OP_MATCH_SUBSTR = 17; // Substring matching operation (|=). Used for string match filter. + BINARY_OP_NOT_MATCH_SUBSTR = 18; // Substring non-matching operation (!=). Used for string match filter. + BINARY_OP_MATCH_RE = 19; // Regular expression matching operation (|~). Used for regex match filter and label matcher. + BINARY_OP_NOT_MATCH_RE = 20; // Regular expression non-matching operation (!~). Used for regex match filter and label matcher. + BINARY_OP_MATCH_PATTERN = 21; // Pattern matching operation (|>). Used for pattern match filter. + BINARY_OP_NOT_MATCH_PATTERN = 22; // Pattern non-matching operation (!>). Use for pattern match filter. +} + +// LiteralExpression represents a constant literal value in an expression tree. +message LiteralExpression { + oneof kind { + NullLiteral null_literal = 1; + BoolLiteral bool_literal = 2; + StringLiteral string_literal = 3; + IntegerLiteral integer_literal = 4; + FloatLiteral float_literal = 5; + TimestampLiteral timestamp_literal = 6; + DurationLiteral duration_literal = 7; + BytesLiteral bytes_literal = 8; + } +} + +// NullLiteral represents a null literal value. +message NullLiteral {} + +// BoolLiteral represents a boolean literal value. +message BoolLiteral { + bool value = 1; +} + +// StringLiteral represents a string literal value. +message StringLiteral { + string value = 1; +} + +// IntegerLiteral represents a signed integer literal value. +message IntegerLiteral { + int64 value = 1; +} + +// FloatLiteral represents a floating point literal value. +message FloatLiteral { + double value = 1; +} + +// TimestampLiteral represents a timestamp literal value in nanoseconds since +// the Unix epoch. +message TimestampLiteral { + int64 value = 1; +} + +// DurationLiteral represents a duration literal value in nanoseconds. +message DurationLiteral { + int64 value = 1; +} + +// BytesLiteral represents a bytes count literal value. +message BytesLiteral { + int64 value = 1; +} + +// ColumnExpression is an expression used to reference a column. +message ColumnExpression { + string name = 1; // Name of the column being referenced. + ColumnType type = 2; // Type of the column being referenced. +} + +// ColumnType holds valid types of columns that can be referenced. +enum ColumnType { + COLUMN_TYPE_INVALID = 0; // Invalid column type. + + COLUMN_TYPE_BUILTIN = 1; // COLUMN_TYPE_BUILTIN represents a builtin column (such as timestamp). + COLUMN_TYPE_LABEL = 2; // COLUMN_TYPE_LABEL represents a column from a stream label. + COLUMN_TYPE_METADATA = 3; // COLUMN_TYPE_METADATA represents a column from a log metadata. + COLUMN_TYPE_PARSED = 4; // COLUMN_TYPE_PARSED represents a parsed column from a parser stage. + COLUMN_TYPE_AMBIGUOUS = 5; // COLUMN_TYPE_AMBIGUOUS represents a column that can either be a builtin, label, metadata, or parsed. + COLUMN_TYPE_GENERATED = 6; // COLUMN_TYPE_GENERATED represents a column that is generated from an expression or computation. +} diff --git a/pkg/engine/internal/planner/physical/physicalpb/physicalpb.go b/pkg/engine/internal/planner/physical/physicalpb/physicalpb.go new file mode 100644 index 0000000000000..ffaf80046ad8e --- /dev/null +++ b/pkg/engine/internal/planner/physical/physicalpb/physicalpb.go @@ -0,0 +1,786 @@ +// Package physicalpb contains the protobuf definitions for physical plan nodes. +package physicalpb + +import ( + "errors" + fmt "fmt" + "iter" + "slices" + + "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" + "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid" +) + +type NodeKind uint8 + +const ( + NodeKindInvalid NodeKind = iota // NodeKindInvalid is an invalid NodeKind. + NodeKindDataObjScan // NodeKindDataObjScan is used for [DataObjScan]. + NodeKindSortMerge // NodeKindSortMerge is used for [SortMerge]. + NodeKindProjection // NodeKindProjection is used for [Projection]. + NodeKindFilter // NodeKindFilter is used for [Filter]. + NodeKindLimit // NodeKindLimit is used for [Limit]. + NodeKindAggregateRange // NodeKindAggregateRange is used for [AggregateRange]. + NodeKindAggregateVector // NodeKindAggregateVector is used for [AggregateVector]. + NodeKindMerge // NodeKindMerge is used for [Merge]. + NodeKindParse // NodeKindParse is used for [Parse]. + NodeKindColumnCompat // NodeKindColumnCompat is used for [ColumnCompat]. + NodeKindTopK // NodeKindTopK is used for [TopK]. + NodeKindScanSet // NodeKindScanSet is used for [ScanSet]. + NodeKindParallelize // NodeKindParallelize is used for [Parallelize]. + NodeKindJoin // NodeKindJoin is used for [Join]. +) + +var nodeKinds = [...]string{ + NodeKindInvalid: "invalid", + NodeKindDataObjScan: "DataObjScan", + NodeKindSortMerge: "SortMerge", + NodeKindProjection: "Projection", + NodeKindFilter: "Filter", + NodeKindLimit: "Limit", + NodeKindAggregateRange: "AggregateRange", + NodeKindAggregateVector: "AggregateVector", + NodeKindMerge: "Merge", + NodeKindParse: "Parse", + NodeKindColumnCompat: "ColumnCompat", + NodeKindTopK: "TopK", + NodeKindScanSet: "ScanSet", + NodeKindParallelize: "Parallelize", + NodeKindJoin: "Join", +} + +func (k NodeKind) String() string { + if int(k) < len(nodeKinds) { + return nodeKinds[k] + } + return fmt.Sprintf("NodeKind(%d)", k) +} + +// Node represents a single operation in a physical execution plan. It defines +// the core interface that all physical plan nodes must implement. +type Node interface { + // isNode is a marker interface to denote a Node so that only types within this package + // can implement this interface. + isNode() + + // ID returns a string that uniquely identifies a node in the plan. + ID() string + + // ulid returns the ULID value that uniquely identifies a node in the plan. + ulid() ulid.ULID + + // Kind returns the kind for this node. + Kind() NodeKind + + // Accept allows the node to be visited by a [Visitor], calling back to the + // appropriate Node-specific Visit method on the Visitor interface. + Accept(Visitor) error + + // ToPlanNode converts the node to a PlanNode. + ToPlanNode() *PlanNode + + // Clone returns a deep copy of the node (minus its ID). + Clone() Node + + // CloneWithNewID returns a deep copy of the node with a new ID. + CloneWithNewID() Node +} + +// GetNode returns the underlying Node from the PlanNode. +func GetNode(planNode *PlanNode) Node { + switch kind := planNode.Kind.(type) { + case *PlanNode_AggregateRange: + return kind.AggregateRange + case *PlanNode_AggregateVector: + return kind.AggregateVector + case *PlanNode_Scan: + return kind.Scan + case *PlanNode_Filter: + return kind.Filter + case *PlanNode_Limit: + return kind.Limit + case *PlanNode_Merge: + return kind.Merge + case *PlanNode_Parse: + return kind.Parse + case *PlanNode_Projection: + return kind.Projection + case *PlanNode_SortMerge: + return kind.SortMerge + case *PlanNode_ColumnCompat: + return kind.ColumnCompat + case *PlanNode_TopK: + return kind.TopK + case *PlanNode_ScanSet: + return kind.ScanSet + case *PlanNode_Parallelize: + return kind.Parallelize + case *PlanNode_Join: + return kind.Join + default: + panic(fmt.Sprintf("unknown node kind %T", kind)) + } +} + +// Visitor defines an interface for visiting each type of Node. +type Visitor interface { + VisitAggregateRange(*AggregateRange) error + VisitAggregateVector(*AggregateVector) error + VisitDataObjScan(*DataObjScan) error + VisitFilter(*Filter) error + VisitLimit(*Limit) error + VisitMerge(*Merge) error + VisitParse(*Parse) error + VisitProjection(*Projection) error + VisitSortMerge(*SortMerge) error + VisitColumnCompat(*ColumnCompat) error + VisitTopK(*TopK) error + VisitScanSet(*ScanSet) error + VisitParallelize(*Parallelize) error + VisitJoin(*Join) error +} + +// +// Implementations of the Node interface for each type. +// + +func (n *AggregateRange) isNode() {} +func (n *AggregateVector) isNode() {} +func (n *DataObjScan) isNode() {} +func (n *Filter) isNode() {} +func (n *Limit) isNode() {} +func (n *Merge) isNode() {} +func (n *Parse) isNode() {} +func (n *Projection) isNode() {} +func (n *SortMerge) isNode() {} +func (n *ColumnCompat) isNode() {} +func (n *TopK) isNode() {} +func (n *ScanSet) isNode() {} +func (n *Parallelize) isNode() {} +func (n *Join) isNode() {} + +func (n *AggregateRange) ID() string { return n.GetId().Value.String() } +func (n *AggregateVector) ID() string { return n.GetId().Value.String() } +func (n *DataObjScan) ID() string { return n.GetId().Value.String() } +func (n *Filter) ID() string { return n.GetId().Value.String() } +func (n *Limit) ID() string { return n.GetId().Value.String() } +func (n *Merge) ID() string { return n.GetId().Value.String() } +func (n *Parse) ID() string { return n.GetId().Value.String() } +func (n *Projection) ID() string { return n.GetId().Value.String() } +func (n *SortMerge) ID() string { return n.GetId().Value.String() } +func (n *ColumnCompat) ID() string { return n.GetId().Value.String() } +func (n *TopK) ID() string { return n.GetId().Value.String() } +func (n *ScanSet) ID() string { return n.GetId().Value.String() } +func (n *Parallelize) ID() string { return n.GetId().Value.String() } +func (n *Join) ID() string { return n.GetId().Value.String() } + +func (n *AggregateRange) ulid() ulid.ULID { return n.GetId().Value } +func (n *AggregateVector) ulid() ulid.ULID { return n.GetId().Value } +func (n *DataObjScan) ulid() ulid.ULID { return n.GetId().Value } +func (n *Filter) ulid() ulid.ULID { return n.GetId().Value } +func (n *Limit) ulid() ulid.ULID { return n.GetId().Value } +func (n *Merge) ulid() ulid.ULID { return n.GetId().Value } +func (n *Parse) ulid() ulid.ULID { return n.GetId().Value } +func (n *Projection) ulid() ulid.ULID { return n.GetId().Value } +func (n *SortMerge) ulid() ulid.ULID { return n.GetId().Value } +func (n *ColumnCompat) ulid() ulid.ULID { return n.GetId().Value } +func (n *TopK) ulid() ulid.ULID { return n.GetId().Value } +func (n *ScanSet) ulid() ulid.ULID { return n.GetId().Value } +func (n *Parallelize) ulid() ulid.ULID { return n.GetId().Value } +func (n *Join) ulid() ulid.ULID { return n.GetId().Value } + +func (n *AggregateRange) Kind() NodeKind { return NodeKindAggregateRange } +func (n *AggregateVector) Kind() NodeKind { return NodeKindAggregateVector } +func (n *DataObjScan) Kind() NodeKind { return NodeKindDataObjScan } +func (n *Filter) Kind() NodeKind { return NodeKindFilter } +func (n *Limit) Kind() NodeKind { return NodeKindLimit } +func (n *Merge) Kind() NodeKind { return NodeKindMerge } +func (n *Parse) Kind() NodeKind { return NodeKindParse } +func (n *Projection) Kind() NodeKind { return NodeKindProjection } +func (n *SortMerge) Kind() NodeKind { return NodeKindSortMerge } +func (n *ColumnCompat) Kind() NodeKind { return NodeKindColumnCompat } +func (n *TopK) Kind() NodeKind { return NodeKindTopK } +func (n *ScanSet) Kind() NodeKind { return NodeKindScanSet } +func (n *Parallelize) Kind() NodeKind { return NodeKindParallelize } +func (n *Join) Kind() NodeKind { return NodeKindJoin } + +func (n *AggregateRange) Accept(v Visitor) error { return v.VisitAggregateRange(n) } +func (n *AggregateVector) Accept(v Visitor) error { return v.VisitAggregateVector(n) } +func (n *DataObjScan) Accept(v Visitor) error { return v.VisitDataObjScan(n) } +func (n *Filter) Accept(v Visitor) error { return v.VisitFilter(n) } +func (n *Limit) Accept(v Visitor) error { return v.VisitLimit(n) } +func (n *Merge) Accept(v Visitor) error { return v.VisitMerge(n) } +func (n *Parse) Accept(v Visitor) error { return v.VisitParse(n) } +func (n *Projection) Accept(v Visitor) error { return v.VisitProjection(n) } +func (n *SortMerge) Accept(v Visitor) error { return v.VisitSortMerge(n) } +func (n *ColumnCompat) Accept(v Visitor) error { return v.VisitColumnCompat(n) } +func (n *TopK) Accept(v Visitor) error { return v.VisitTopK(n) } +func (n *ScanSet) Accept(v Visitor) error { return v.VisitScanSet(n) } +func (n *Parallelize) Accept(v Visitor) error { return v.VisitParallelize(n) } +func (n *Join) Accept(v Visitor) error { return v.VisitJoin(n) } + +func (n *AggregateRange) ToPlanNode() *PlanNode { return planNode(&PlanNode_AggregateRange{n}) } +func (n *AggregateVector) ToPlanNode() *PlanNode { return planNode(&PlanNode_AggregateVector{n}) } +func (n *DataObjScan) ToPlanNode() *PlanNode { return planNode(&PlanNode_Scan{n}) } +func (n *Filter) ToPlanNode() *PlanNode { return planNode(&PlanNode_Filter{n}) } +func (n *Limit) ToPlanNode() *PlanNode { return planNode(&PlanNode_Limit{n}) } +func (n *Merge) ToPlanNode() *PlanNode { return planNode(&PlanNode_Merge{n}) } +func (n *Parse) ToPlanNode() *PlanNode { return planNode(&PlanNode_Parse{n}) } +func (n *Projection) ToPlanNode() *PlanNode { return planNode(&PlanNode_Projection{n}) } +func (n *SortMerge) ToPlanNode() *PlanNode { return planNode(&PlanNode_SortMerge{n}) } +func (n *ColumnCompat) ToPlanNode() *PlanNode { return planNode(&PlanNode_ColumnCompat{n}) } +func (n *TopK) ToPlanNode() *PlanNode { return planNode(&PlanNode_TopK{n}) } +func (n *ScanSet) ToPlanNode() *PlanNode { return planNode(&PlanNode_ScanSet{n}) } +func (n *Parallelize) ToPlanNode() *PlanNode { return planNode(&PlanNode_Parallelize{n}) } +func (n *Join) ToPlanNode() *PlanNode { return planNode(&PlanNode_Join{n}) } + +// Clone returns a deep copy of the node (minus its ID). +func (n *AggregateRange) Clone() Node { + return &AggregateRange{ + PartitionBy: cloneColExpressions(n.PartitionBy), + Operation: n.Operation, + StartUnixNanos: n.StartUnixNanos, + EndUnixNanos: n.EndUnixNanos, + StepNs: n.StepNs, + RangeNs: n.RangeNs, + } +} +func (n *AggregateVector) Clone() Node { + return &AggregateVector{ + GroupBy: cloneColExpressions(n.GroupBy), + Operation: n.Operation, + } +} +func (n *DataObjScan) Clone() Node { + return &DataObjScan{ + Location: n.Location, + Section: n.Section, + StreamIds: slices.Clone(n.StreamIds), + Projections: cloneColExpressions(n.Projections), + Predicates: cloneExpressions(n.Predicates), + } +} +func (n *Filter) Clone() Node { + return &Filter{ + Predicates: cloneExpressions(n.Predicates), + } +} +func (n *Limit) Clone() Node { + return &Limit{ + Skip: n.Skip, + Fetch: n.Fetch, + } +} +func (n *Merge) Clone() Node { + return &Merge{} +} +func (n *Parse) Clone() Node { + return &Parse{ + Operation: n.Operation, + RequestedKeys: slices.Clone(n.RequestedKeys), + } +} +func (n *Projection) Clone() Node { + return &Projection{ + Expressions: cloneExpressions(n.Expressions), + All: n.All, + Expand: n.Expand, + Drop: n.Drop, + } +} +func (n *SortMerge) Clone() Node { + tmpCol := n.Column.Clone() + return &SortMerge{ + Column: tmpCol.GetColumnExpression(), + Order: n.Order, + } +} +func (n *ColumnCompat) Clone() Node { + return &ColumnCompat{ + Source: n.Source, + Destination: n.Destination, + Collision: n.Collision, + } +} +func (n *TopK) Clone() Node { + tmp := (*n.SortBy).Clone() + return &TopK{ + SortBy: tmp.GetColumnExpression(), + Ascending: n.Ascending, + NullsFirst: n.NullsFirst, + K: n.K, + } +} +func (n *ScanSet) Clone() Node { + newTargets := make([]*ScanTarget, 0, len(n.Targets)) + for _, target := range n.Targets { + newTargets = append(newTargets, target.Clone()) + } + + return &ScanSet{Targets: newTargets} +} +func (n *Parallelize) Clone() Node { + return &Parallelize{ /* nothing to clone */ } +} + +func (n *Join) Clone() Node { + return &Join{ /* nothing to clone */ } +} + +func (t *ScanTarget) Clone() *ScanTarget { + res := &ScanTarget{Type: t.Type} + if t.DataObject != nil { + res.DataObject = t.DataObject.Clone().(*DataObjScan) + } + return res +} + +// CloneWithNewID returns a deep copy of the node with a new ID. +func (n *AggregateRange) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetAggregateRange() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *AggregateVector) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetAggregateVector() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *DataObjScan) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetScan() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *Filter) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetFilter() + tmp.Id = PlanNodeID{ulid.New()} + return tmp + +} +func (n *Limit) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetLimit() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *Merge) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetMerge() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *Parse) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetParse() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *Projection) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetProjection() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *SortMerge) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetSortMerge() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *ColumnCompat) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetColumnCompat() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *TopK) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetTopK() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *ScanSet) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetScanSet() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *Parallelize) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetParallelize() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} +func (n *Join) CloneWithNewID() Node { + tmp := n.Clone().ToPlanNode().GetJoin() + tmp.Id = PlanNodeID{ulid.New()} + return tmp +} + +func planNode(kind isPlanNode_Kind) *PlanNode { + return &PlanNode{Kind: kind} +} + +// ShardableNode is a Node that can be split into multiple smaller partitions. +type ShardableNode interface { + Node + + // Shards produces a sequence of nodes that represent a fragment of the + // original node. Returned nodes do not need to be the same type as the + // original node. + // + // Implementations must produce unique values of Node in each call to + // Shards. + Shards() iter.Seq[Node] +} + +// Shards returns an iterator over the shards of the scan. Each emitted shard +// will be a clone. Projections and predicates on the ScanSet are cloned and +// applied to each shard. +// +// Shards panics if one of the targets is invalid. +func (n *ScanSet) Shards() iter.Seq[Node] { + return func(yield func(Node) bool) { + for _, target := range n.Targets { + switch target.Type { + case SCAN_TYPE_DATA_OBJECT: + node := target.DataObject.Clone().(*DataObjScan) + node.Projections = cloneColExpressions(n.Projections) + node.Predicates = cloneExpressions(n.Predicates) + + if !yield(node) { + return + } + + default: + panic(fmt.Sprintf("invalid scan type %s", target.Type)) + } + } + } +} + +var SupportedRangeAggregationTypes = []AggregateRangeOp{ + AGGREGATE_RANGE_OP_COUNT, AGGREGATE_RANGE_OP_SUM, AGGREGATE_RANGE_OP_MAX, AGGREGATE_RANGE_OP_MIN, +} + +var SupportedVectorAggregationTypes = []AggregateVectorOp{AGGREGATE_VECTOR_OP_SUM, AGGREGATE_VECTOR_OP_MAX, AGGREGATE_VECTOR_OP_MIN, AGGREGATE_VECTOR_OP_COUNT} + +// ColumnTypePrecedence returns the precedence of the given [ColumnType]. +func ColumnTypePrecedence(ct ColumnType) int { + switch ct { + case COLUMN_TYPE_GENERATED: + return PrecedenceGenerated + case COLUMN_TYPE_PARSED: + return PrecedenceParsed + case COLUMN_TYPE_METADATA: + return PrecedenceMetadata + case COLUMN_TYPE_LABEL: + return PrecedenceLabel + default: + return PrecedenceBuiltin // Default to lowest precedence + } +} + +// Column type precedence for ambiguous column resolution (highest to lowest): +// Generated > Parsed > Metadata > Label > Builtin +const ( + PrecedenceGenerated = iota // 0 - highest precedence + + PrecedenceParsed // 1 + PrecedenceMetadata // 2 + PrecedenceLabel // 3 + PrecedenceBuiltin // 4 - lowest precedence +) + +var ctNames = [7]string{"invalid", "builtin", "label", "metadata", "parsed", "ambiguous", "generated"} + +// ColumnTypeFromString returns the [ColumnType] from its string representation. +func ColumnTypeFromString(ct string) ColumnType { + switch ct { + case ctNames[1]: + return COLUMN_TYPE_BUILTIN + case ctNames[2]: + return COLUMN_TYPE_LABEL + case ctNames[3]: + return COLUMN_TYPE_METADATA + case ctNames[4]: + return COLUMN_TYPE_PARSED + case ctNames[5]: + return COLUMN_TYPE_AMBIGUOUS + case ctNames[6]: + return COLUMN_TYPE_GENERATED + default: + panic(fmt.Sprintf("invalid column type: %s", ct)) + } +} + +func (p *Plan) NodeById(id PlanNodeID) Node { + for _, n := range p.Nodes { + if GetNode(n).ulid() == id.Value { + return GetNode(n) + } + } + return nil +} + +func (p *Plan) NodeByStringId(id string) Node { + for _, n := range p.Nodes { + if GetNode(n).ID() == id { + return GetNode(n) + } + } + return nil +} + +func (p *Plan) Roots() []Node { + if len(p.Nodes) == 0 { + return nil + } + + var nodes = p.Nodes + roots := []Node{} + for _, n := range nodes { + roots = append(roots, GetNode(n)) + } + for _, edge := range p.Edges { + if i := slices.Index(roots, p.NodeById(edge.Child)); i >= 0 { + roots = append(roots[:i], roots[i+1:]...) + } + } + return roots +} + +func (p *Plan) Root() (Node, error) { + roots := p.Roots() + if len(roots) == 0 { + return nil, fmt.Errorf("plan has no root node") + } + if len(roots) == 1 { + return roots[0], nil + } + return nil, fmt.Errorf("plan has multiple root nodes") +} + +func (p *Plan) Leaves() []Node { + if len(p.Nodes) == 0 { + return nil + } + + var nodes = p.Nodes + leaves := []Node{} + for _, n := range nodes { + leaves = append(leaves, GetNode(n)) + } + for _, edge := range p.Edges { + if i := slices.Index(leaves, p.NodeById(edge.Parent)); i >= 0 { + leaves = append(leaves[:i], leaves[i+1:]...) + } + } + return leaves +} + +func (p *Plan) Parents(n Node) []Node { + parents := []Node{} + for _, e := range p.Edges { + if e.Child.Value == n.ulid() { + parents = append(parents, p.NodeById(e.Parent)) + } + } + return parents +} + +func (p *Plan) Children(n Node) []Node { + children := []Node{} + for _, e := range p.Edges { + if e.Parent.Value == n.ulid() { + children = append(children, p.NodeById(e.Child)) + } + } + return children +} + +func (p *Plan) Add(n Node) *PlanNode { + if n == nil { + return nil + } + if p.NodeById(PlanNodeID{n.ulid()}) == nil { // only add if it's not already present + p.Nodes = append(p.Nodes, n.ToPlanNode()) + } + return n.ToPlanNode() +} + +func (p *Plan) AddEdge(e dag.Edge[Node]) error { + if (e.Parent == nil) || (e.Child == nil) { + return fmt.Errorf("parent and child nodes must not be zero values") + } + if e.Parent.ID() == e.Child.ID() { + return fmt.Errorf("cannot connect a node (%v) to itself", e.Parent.ID()) + } + if p.NodeByStringId(e.Parent.ID()) == nil || p.NodeByStringId(e.Child.ID()) == nil { + return fmt.Errorf("both nodes %v and %v must already exist in the plan", e.Parent.ID(), e.Child.ID()) + } + for _, edge := range p.Edges { + if (edge.Parent.Value == e.Parent.ulid()) && (edge.Child.Value == e.Child.ulid()) { + return fmt.Errorf("edge between node %v and %v already exists", e.Parent.ID(), e.Child.ID()) + } + } + p.Edges = append(p.Edges, &PlanEdge{PlanNodeID{Value: e.Parent.ulid()}, PlanNodeID{Value: e.Child.ulid()}}) + return nil +} + +func (p *Plan) Eliminate(n Node) { + if p.NodeByStringId(n.ID()) == nil { + return // no node to eliminate + } + // For each parent p in the node to eliminate, push up n's children to + // become children of p, and remove n as a child of p. + parents := p.Parents(n) + + // First remove n as a child of p + for i := 0; i < len(p.Edges); i++ { + edge := p.Edges[i] + if edge.Child.Value.String() == n.ID() { + p.Edges = append(p.Edges[:i], p.Edges[i+1:]...) + i-- + } + } + + // Now push up n's children to become children of p + for _, child := range p.Children(n) { + for _, parent := range parents { + edgeExists := false + for _, e := range p.Edges { + if e.Parent.Value.String() == parent.ID() && e.Child.Value.String() == child.ID() { + // edge already exists, skip + edgeExists = true + } + } + if !edgeExists { + p.AddEdge(dag.Edge[Node]{Parent: parent, Child: child}) + } + } + } + // Next remove n as a parent of n's children + for i := 0; i < len(p.Edges); i++ { + edge := p.Edges[i] + if edge.Parent.Value.String() == n.ID() { + p.Edges = append(p.Edges[:i], p.Edges[i+1:]...) + i-- + } + } + + // Finally, remove n + var nodeIds []ulid.ULID + for _, node := range p.Nodes { + nodeIds = append(nodeIds, GetNode(node).ulid()) + } + nodeIdx := slices.Index(nodeIds, n.ulid()) // guaranteed to be >=0 since we found n earlier + p.Nodes = append(p.Nodes[:nodeIdx], p.Nodes[nodeIdx+1:]...) +} + +// Inject injects a new node between a parent and its children: +// +// * The children of parent become children of node. +// * The child of parent becomes node. +// +// Inject panics if given a node that already exists in the plan. +// +// For convenience, Inject returns node without modification. +func (p *Plan) Inject(parent, node Node) Node { + if p.NodeByStringId(node.ID()) != nil { + panic("injectNode: target node already exists in plan") + } + p.Add(node) + + // Update parent's children so that their parent is node. + for i := 0; i < len(p.Edges); i++ { + if p.Edges[i].Parent.Value.String() == parent.ID() { + p.AddEdge(dag.Edge[Node]{Parent: node, Child: p.NodeByStringId(p.Edges[i].Child.Value.String())}) + p.Edges = append(p.Edges[:i], p.Edges[i+1:]...) + i-- + } + } + + // Add an edge between parent and node. + p.AddEdge(dag.Edge[Node]{Parent: parent, Child: node}) + return node +} + +// WalkFunc is a function that gets invoked when walking a Graph. Walking will +// stop if WalkFunc returns a non-nil error. +type WalkFunc func(n Node) error + +func (p *Plan) VisitorWalk(n Node, v Visitor, o WalkOrder) error { + return p.Walk(n, func(n Node) error { return n.Accept(v) }, o) +} + +// Walk performs a depth-first walk of outgoing edges for all nodes in start, +// invoking the provided fn for each node. Walk returns the error returned by +// fn. +// +// Nodes unreachable from start will not be passed to fn. +func (p *Plan) Walk(n Node, f WalkFunc, order WalkOrder) error { + visited := map[Node]bool{} + switch order { + case PRE_ORDER_WALK: + return p.preOrderWalk(n, f, visited) + case POST_ORDER_WALK: + return p.postOrderWalk(n, f, visited) + default: + return errors.New("unsupported walk order. must be one of PreOrderWalk and PostOrderWalk") + } +} + +func (p *Plan) preOrderWalk(n Node, f WalkFunc, visited map[Node]bool) error { + if visited[n] { + return nil + } + visited[n] = true + + if err := f(n); err != nil { + return err + } + + for _, child := range p.Children(n) { + if err := p.preOrderWalk(child, f, visited); err != nil { + return err + } + } + return nil +} + +func (p *Plan) postOrderWalk(n Node, f WalkFunc, visited map[Node]bool) error { + if visited[n] { + return nil + } + visited[n] = true + + for _, child := range p.Children(n) { + if err := p.postOrderWalk(child, f, visited); err != nil { + return err + } + } + + return f(n) +} + +// FromGraph constructs a Plan from a given DAG. +func FromGraph(graph dag.Graph[Node]) *Plan { + p := &Plan{} + for _, root := range graph.Roots() { + fromGraphHelper(p, graph, root) + } + return p +} + +func fromGraphHelper(p *Plan, g dag.Graph[Node], n Node) { + p.Add(n) + for _, c := range g.Children(n) { + p.Add(c) + p.AddEdge(dag.Edge[Node]{Parent: n, Child: c}) + fromGraphHelper(p, g, c) + } +} + +// Graph returns the underlying graph of the plan. +func (p *Plan) Graph() *dag.Graph[Node] { + g := &dag.Graph[Node]{} + for _, n := range p.Nodes { + g.Add(GetNode(n)) + } + for _, e := range p.Edges { + g.AddEdge(dag.Edge[Node]{Parent: p.NodeById(e.Parent), Child: p.NodeById(e.Child)}) + } + return g +} diff --git a/pkg/engine/internal/planner/physical/physicalpb/physicalpb.pb.go b/pkg/engine/internal/planner/physical/physicalpb/physicalpb.pb.go new file mode 100644 index 0000000000000..901eb3f61f1d0 --- /dev/null +++ b/pkg/engine/internal/planner/physical/physicalpb/physicalpb.pb.go @@ -0,0 +1,8626 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pkg/engine/internal/planner/physical/physicalpb/physicalpb.proto + +package physicalpb + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + _ "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid" + github_com_grafana_loki_v3_pkg_engine_internal_util_ulid "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid" + io "io" + math "math" + math_bits "math/bits" + reflect "reflect" + strconv "strconv" + strings "strings" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type WalkOrder int32 + +const ( + PRE_ORDER_WALK WalkOrder = 0 + POST_ORDER_WALK WalkOrder = 1 +) + +var WalkOrder_name = map[int32]string{ + 0: "PRE_ORDER_WALK", + 1: "POST_ORDER_WALK", +} + +var WalkOrder_value = map[string]int32{ + "PRE_ORDER_WALK": 0, + "POST_ORDER_WALK": 1, +} + +func (WalkOrder) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{0} +} + +// AggregateRangeOp represents the operation to perform on the aggregated +// data. +type AggregateRangeOp int32 + +const ( + AGGREGATE_RANGE_OP_INVALID AggregateRangeOp = 0 + AGGREGATE_RANGE_OP_COUNT AggregateRangeOp = 1 + AGGREGATE_RANGE_OP_SUM AggregateRangeOp = 2 + AGGREGATE_RANGE_OP_MAX AggregateRangeOp = 3 + AGGREGATE_RANGE_OP_MIN AggregateRangeOp = 4 +) + +var AggregateRangeOp_name = map[int32]string{ + 0: "AGGREGATE_RANGE_OP_INVALID", + 1: "AGGREGATE_RANGE_OP_COUNT", + 2: "AGGREGATE_RANGE_OP_SUM", + 3: "AGGREGATE_RANGE_OP_MAX", + 4: "AGGREGATE_RANGE_OP_MIN", +} + +var AggregateRangeOp_value = map[string]int32{ + "AGGREGATE_RANGE_OP_INVALID": 0, + "AGGREGATE_RANGE_OP_COUNT": 1, + "AGGREGATE_RANGE_OP_SUM": 2, + "AGGREGATE_RANGE_OP_MAX": 3, + "AGGREGATE_RANGE_OP_MIN": 4, +} + +func (AggregateRangeOp) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{1} +} + +// AggregateVectorOp represents the different aggregation operations that can +// be performed on a range vector. +type AggregateVectorOp int32 + +const ( + AGGREGATE_VECTOR_OP_INVALID AggregateVectorOp = 0 + AGGREGATE_VECTOR_OP_SUM AggregateVectorOp = 1 + AGGREGATE_VECTOR_OP_MAX AggregateVectorOp = 2 + AGGREGATE_VECTOR_OP_MIN AggregateVectorOp = 3 + AGGREGATE_VECTOR_OP_COUNT AggregateVectorOp = 4 + AGGREGATE_VECTOR_OP_AVG AggregateVectorOp = 5 + AGGREGATE_VECTOR_OP_STDDEV AggregateVectorOp = 6 + AGGREGATE_VECTOR_OP_STDVAR AggregateVectorOp = 7 + AGGREGATE_VECTOR_OP_BOTTOMK AggregateVectorOp = 8 + AGGREGATE_VECTOR_OP_TOPK AggregateVectorOp = 9 + AGGREGATE_VECTOR_OP_SORT AggregateVectorOp = 10 + AGGREGATE_VECTOR_OP_SORT_DESC AggregateVectorOp = 11 +) + +var AggregateVectorOp_name = map[int32]string{ + 0: "AGGREGATE_VECTOR_OP_INVALID", + 1: "AGGREGATE_VECTOR_OP_SUM", + 2: "AGGREGATE_VECTOR_OP_MAX", + 3: "AGGREGATE_VECTOR_OP_MIN", + 4: "AGGREGATE_VECTOR_OP_COUNT", + 5: "AGGREGATE_VECTOR_OP_AVG", + 6: "AGGREGATE_VECTOR_OP_STDDEV", + 7: "AGGREGATE_VECTOR_OP_STDVAR", + 8: "AGGREGATE_VECTOR_OP_BOTTOMK", + 9: "AGGREGATE_VECTOR_OP_TOPK", + 10: "AGGREGATE_VECTOR_OP_SORT", + 11: "AGGREGATE_VECTOR_OP_SORT_DESC", +} + +var AggregateVectorOp_value = map[string]int32{ + "AGGREGATE_VECTOR_OP_INVALID": 0, + "AGGREGATE_VECTOR_OP_SUM": 1, + "AGGREGATE_VECTOR_OP_MAX": 2, + "AGGREGATE_VECTOR_OP_MIN": 3, + "AGGREGATE_VECTOR_OP_COUNT": 4, + "AGGREGATE_VECTOR_OP_AVG": 5, + "AGGREGATE_VECTOR_OP_STDDEV": 6, + "AGGREGATE_VECTOR_OP_STDVAR": 7, + "AGGREGATE_VECTOR_OP_BOTTOMK": 8, + "AGGREGATE_VECTOR_OP_TOPK": 9, + "AGGREGATE_VECTOR_OP_SORT": 10, + "AGGREGATE_VECTOR_OP_SORT_DESC": 11, +} + +func (AggregateVectorOp) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{2} +} + +// ParseOp represents the type of parse operation to be performed. +type ParseOp int32 + +const ( + PARSE_OP_INVALID ParseOp = 0 + PARSE_OP_LOGFMT ParseOp = 1 + PARSE_OP_JSON ParseOp = 2 +) + +var ParseOp_name = map[int32]string{ + 0: "PARSE_OP_INVALID", + 1: "PARSE_OP_LOGFMT", + 2: "PARSE_OP_JSON", +} + +var ParseOp_value = map[string]int32{ + "PARSE_OP_INVALID": 0, + "PARSE_OP_LOGFMT": 1, + "PARSE_OP_JSON": 2, +} + +func (ParseOp) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{3} +} + +// SortOrder represents the order in which results should be sorted. +type SortOrder int32 + +const ( + SORT_ORDER_INVALID SortOrder = 0 + SORT_ORDER_ASCENDING SortOrder = 1 + SORT_ORDER_DESCENDING SortOrder = 2 +) + +var SortOrder_name = map[int32]string{ + 0: "SORT_ORDER_INVALID", + 1: "SORT_ORDER_ASCENDING", + 2: "SORT_ORDER_DESCENDING", +} + +var SortOrder_value = map[string]int32{ + "SORT_ORDER_INVALID": 0, + "SORT_ORDER_ASCENDING": 1, + "SORT_ORDER_DESCENDING": 2, +} + +func (SortOrder) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{4} +} + +// ScanType represents the data being scanned in a target of a [ScanSet]. +type ScanType int32 + +const ( + SCAN_TYPE_INVALID ScanType = 0 + SCAN_TYPE_DATA_OBJECT ScanType = 1 +) + +var ScanType_name = map[int32]string{ + 0: "SCAN_TYPE_INVALID", + 1: "SCAN_TYPE_DATA_OBJECT", +} + +var ScanType_value = map[string]int32{ + "SCAN_TYPE_INVALID": 0, + "SCAN_TYPE_DATA_OBJECT": 1, +} + +func (ScanType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{5} +} + +// Plan represents the physical plan of a query. +type Plan struct { + Nodes []*PlanNode `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"` + Edges []*PlanEdge `protobuf:"bytes,2,rep,name=edges,proto3" json:"edges,omitempty"` +} + +func (m *Plan) Reset() { *m = Plan{} } +func (*Plan) ProtoMessage() {} +func (*Plan) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{0} +} +func (m *Plan) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Plan) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Plan.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Plan) XXX_Merge(src proto.Message) { + xxx_messageInfo_Plan.Merge(m, src) +} +func (m *Plan) XXX_Size() int { + return m.Size() +} +func (m *Plan) XXX_DiscardUnknown() { + xxx_messageInfo_Plan.DiscardUnknown(m) +} + +var xxx_messageInfo_Plan proto.InternalMessageInfo + +func (m *Plan) GetNodes() []*PlanNode { + if m != nil { + return m.Nodes + } + return nil +} + +func (m *Plan) GetEdges() []*PlanEdge { + if m != nil { + return m.Edges + } + return nil +} + +// PlanEdge represents a relationship between two nodes in the physical plan. +type PlanEdge struct { + Parent PlanNodeID `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent"` + Child PlanNodeID `protobuf:"bytes,2,opt,name=child,proto3" json:"child"` +} + +func (m *PlanEdge) Reset() { *m = PlanEdge{} } +func (*PlanEdge) ProtoMessage() {} +func (*PlanEdge) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{1} +} +func (m *PlanEdge) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PlanEdge) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PlanEdge.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PlanEdge) XXX_Merge(src proto.Message) { + xxx_messageInfo_PlanEdge.Merge(m, src) +} +func (m *PlanEdge) XXX_Size() int { + return m.Size() +} +func (m *PlanEdge) XXX_DiscardUnknown() { + xxx_messageInfo_PlanEdge.DiscardUnknown(m) +} + +var xxx_messageInfo_PlanEdge proto.InternalMessageInfo + +func (m *PlanEdge) GetParent() PlanNodeID { + if m != nil { + return m.Parent + } + return PlanNodeID{} +} + +func (m *PlanEdge) GetChild() PlanNodeID { + if m != nil { + return m.Child + } + return PlanNodeID{} +} + +type PlanNodeID struct { + Value github_com_grafana_loki_v3_pkg_engine_internal_util_ulid.ULID `protobuf:"bytes,1,opt,name=value,proto3,customtype=github.com/grafana/loki/v3/pkg/engine/internal/util/ulid.ULID" json:"value"` +} + +func (m *PlanNodeID) Reset() { *m = PlanNodeID{} } +func (*PlanNodeID) ProtoMessage() {} +func (*PlanNodeID) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{2} +} +func (m *PlanNodeID) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PlanNodeID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PlanNodeID.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PlanNodeID) XXX_Merge(src proto.Message) { + xxx_messageInfo_PlanNodeID.Merge(m, src) +} +func (m *PlanNodeID) XXX_Size() int { + return m.Size() +} +func (m *PlanNodeID) XXX_DiscardUnknown() { + xxx_messageInfo_PlanNodeID.DiscardUnknown(m) +} + +var xxx_messageInfo_PlanNodeID proto.InternalMessageInfo + +// PlanNode represents a node in the physical plan. +type PlanNode struct { + // Types that are valid to be assigned to Kind: + // *PlanNode_AggregateRange + // *PlanNode_AggregateVector + // *PlanNode_Scan + // *PlanNode_Filter + // *PlanNode_Limit + // *PlanNode_Merge + // *PlanNode_Parse + // *PlanNode_Projection + // *PlanNode_SortMerge + // *PlanNode_ColumnCompat + // *PlanNode_ScanSet + // *PlanNode_TopK + // *PlanNode_Parallelize + // *PlanNode_Join + Kind isPlanNode_Kind `protobuf_oneof:"kind"` +} + +func (m *PlanNode) Reset() { *m = PlanNode{} } +func (*PlanNode) ProtoMessage() {} +func (*PlanNode) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{3} +} +func (m *PlanNode) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PlanNode) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PlanNode.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PlanNode) XXX_Merge(src proto.Message) { + xxx_messageInfo_PlanNode.Merge(m, src) +} +func (m *PlanNode) XXX_Size() int { + return m.Size() +} +func (m *PlanNode) XXX_DiscardUnknown() { + xxx_messageInfo_PlanNode.DiscardUnknown(m) +} + +var xxx_messageInfo_PlanNode proto.InternalMessageInfo + +type isPlanNode_Kind interface { + isPlanNode_Kind() + Equal(interface{}) bool + MarshalTo([]byte) (int, error) + Size() int +} + +type PlanNode_AggregateRange struct { + AggregateRange *AggregateRange `protobuf:"bytes,1,opt,name=aggregate_range,json=aggregateRange,proto3,oneof"` +} +type PlanNode_AggregateVector struct { + AggregateVector *AggregateVector `protobuf:"bytes,2,opt,name=aggregate_vector,json=aggregateVector,proto3,oneof"` +} +type PlanNode_Scan struct { + Scan *DataObjScan `protobuf:"bytes,3,opt,name=scan,proto3,oneof"` +} +type PlanNode_Filter struct { + Filter *Filter `protobuf:"bytes,4,opt,name=filter,proto3,oneof"` +} +type PlanNode_Limit struct { + Limit *Limit `protobuf:"bytes,5,opt,name=limit,proto3,oneof"` +} +type PlanNode_Merge struct { + Merge *Merge `protobuf:"bytes,6,opt,name=merge,proto3,oneof"` +} +type PlanNode_Parse struct { + Parse *Parse `protobuf:"bytes,7,opt,name=parse,proto3,oneof"` +} +type PlanNode_Projection struct { + Projection *Projection `protobuf:"bytes,8,opt,name=projection,proto3,oneof"` +} +type PlanNode_SortMerge struct { + SortMerge *SortMerge `protobuf:"bytes,9,opt,name=sort_merge,json=sortMerge,proto3,oneof"` +} +type PlanNode_ColumnCompat struct { + ColumnCompat *ColumnCompat `protobuf:"bytes,10,opt,name=column_compat,json=columnCompat,proto3,oneof"` +} +type PlanNode_ScanSet struct { + ScanSet *ScanSet `protobuf:"bytes,11,opt,name=scan_set,json=scanSet,proto3,oneof"` +} +type PlanNode_TopK struct { + TopK *TopK `protobuf:"bytes,12,opt,name=top_k,json=topK,proto3,oneof"` +} +type PlanNode_Parallelize struct { + Parallelize *Parallelize `protobuf:"bytes,13,opt,name=parallelize,proto3,oneof"` +} +type PlanNode_Join struct { + Join *Join `protobuf:"bytes,14,opt,name=join,proto3,oneof"` +} + +func (*PlanNode_AggregateRange) isPlanNode_Kind() {} +func (*PlanNode_AggregateVector) isPlanNode_Kind() {} +func (*PlanNode_Scan) isPlanNode_Kind() {} +func (*PlanNode_Filter) isPlanNode_Kind() {} +func (*PlanNode_Limit) isPlanNode_Kind() {} +func (*PlanNode_Merge) isPlanNode_Kind() {} +func (*PlanNode_Parse) isPlanNode_Kind() {} +func (*PlanNode_Projection) isPlanNode_Kind() {} +func (*PlanNode_SortMerge) isPlanNode_Kind() {} +func (*PlanNode_ColumnCompat) isPlanNode_Kind() {} +func (*PlanNode_ScanSet) isPlanNode_Kind() {} +func (*PlanNode_TopK) isPlanNode_Kind() {} +func (*PlanNode_Parallelize) isPlanNode_Kind() {} +func (*PlanNode_Join) isPlanNode_Kind() {} + +func (m *PlanNode) GetKind() isPlanNode_Kind { + if m != nil { + return m.Kind + } + return nil +} + +func (m *PlanNode) GetAggregateRange() *AggregateRange { + if x, ok := m.GetKind().(*PlanNode_AggregateRange); ok { + return x.AggregateRange + } + return nil +} + +func (m *PlanNode) GetAggregateVector() *AggregateVector { + if x, ok := m.GetKind().(*PlanNode_AggregateVector); ok { + return x.AggregateVector + } + return nil +} + +func (m *PlanNode) GetScan() *DataObjScan { + if x, ok := m.GetKind().(*PlanNode_Scan); ok { + return x.Scan + } + return nil +} + +func (m *PlanNode) GetFilter() *Filter { + if x, ok := m.GetKind().(*PlanNode_Filter); ok { + return x.Filter + } + return nil +} + +func (m *PlanNode) GetLimit() *Limit { + if x, ok := m.GetKind().(*PlanNode_Limit); ok { + return x.Limit + } + return nil +} + +func (m *PlanNode) GetMerge() *Merge { + if x, ok := m.GetKind().(*PlanNode_Merge); ok { + return x.Merge + } + return nil +} + +func (m *PlanNode) GetParse() *Parse { + if x, ok := m.GetKind().(*PlanNode_Parse); ok { + return x.Parse + } + return nil +} + +func (m *PlanNode) GetProjection() *Projection { + if x, ok := m.GetKind().(*PlanNode_Projection); ok { + return x.Projection + } + return nil +} + +func (m *PlanNode) GetSortMerge() *SortMerge { + if x, ok := m.GetKind().(*PlanNode_SortMerge); ok { + return x.SortMerge + } + return nil +} + +func (m *PlanNode) GetColumnCompat() *ColumnCompat { + if x, ok := m.GetKind().(*PlanNode_ColumnCompat); ok { + return x.ColumnCompat + } + return nil +} + +func (m *PlanNode) GetScanSet() *ScanSet { + if x, ok := m.GetKind().(*PlanNode_ScanSet); ok { + return x.ScanSet + } + return nil +} + +func (m *PlanNode) GetTopK() *TopK { + if x, ok := m.GetKind().(*PlanNode_TopK); ok { + return x.TopK + } + return nil +} + +func (m *PlanNode) GetParallelize() *Parallelize { + if x, ok := m.GetKind().(*PlanNode_Parallelize); ok { + return x.Parallelize + } + return nil +} + +func (m *PlanNode) GetJoin() *Join { + if x, ok := m.GetKind().(*PlanNode_Join); ok { + return x.Join + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*PlanNode) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*PlanNode_AggregateRange)(nil), + (*PlanNode_AggregateVector)(nil), + (*PlanNode_Scan)(nil), + (*PlanNode_Filter)(nil), + (*PlanNode_Limit)(nil), + (*PlanNode_Merge)(nil), + (*PlanNode_Parse)(nil), + (*PlanNode_Projection)(nil), + (*PlanNode_SortMerge)(nil), + (*PlanNode_ColumnCompat)(nil), + (*PlanNode_ScanSet)(nil), + (*PlanNode_TopK)(nil), + (*PlanNode_Parallelize)(nil), + (*PlanNode_Join)(nil), + } +} + +// AggregateRange aggregates samples into windowed ranges. +type AggregateRange struct { + // ID for the node. + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + // Columns to partition the data by. + PartitionBy []*ColumnExpression `protobuf:"bytes,2,rep,name=partition_by,json=partitionBy,proto3" json:"partition_by,omitempty"` + Operation AggregateRangeOp `protobuf:"varint,3,opt,name=operation,proto3,enum=physical.engine.loki.v1.AggregateRangeOp" json:"operation,omitempty"` + StartUnixNanos int64 `protobuf:"varint,4,opt,name=start_unix_nanos,json=startUnixNanos,proto3" json:"start_unix_nanos,omitempty"` + EndUnixNanos int64 `protobuf:"varint,5,opt,name=end_unix_nanos,json=endUnixNanos,proto3" json:"end_unix_nanos,omitempty"` + StepNs int64 `protobuf:"varint,6,opt,name=step_ns,json=stepNs,proto3" json:"step_ns,omitempty"` + RangeNs int64 `protobuf:"varint,7,opt,name=range_ns,json=rangeNs,proto3" json:"range_ns,omitempty"` +} + +func (m *AggregateRange) Reset() { *m = AggregateRange{} } +func (*AggregateRange) ProtoMessage() {} +func (*AggregateRange) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{4} +} +func (m *AggregateRange) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AggregateRange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AggregateRange.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AggregateRange) XXX_Merge(src proto.Message) { + xxx_messageInfo_AggregateRange.Merge(m, src) +} +func (m *AggregateRange) XXX_Size() int { + return m.Size() +} +func (m *AggregateRange) XXX_DiscardUnknown() { + xxx_messageInfo_AggregateRange.DiscardUnknown(m) +} + +var xxx_messageInfo_AggregateRange proto.InternalMessageInfo + +func (m *AggregateRange) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *AggregateRange) GetPartitionBy() []*ColumnExpression { + if m != nil { + return m.PartitionBy + } + return nil +} + +func (m *AggregateRange) GetOperation() AggregateRangeOp { + if m != nil { + return m.Operation + } + return AGGREGATE_RANGE_OP_INVALID +} + +func (m *AggregateRange) GetStartUnixNanos() int64 { + if m != nil { + return m.StartUnixNanos + } + return 0 +} + +func (m *AggregateRange) GetEndUnixNanos() int64 { + if m != nil { + return m.EndUnixNanos + } + return 0 +} + +func (m *AggregateRange) GetStepNs() int64 { + if m != nil { + return m.StepNs + } + return 0 +} + +func (m *AggregateRange) GetRangeNs() int64 { + if m != nil { + return m.RangeNs + } + return 0 +} + +// AggregateVector represents an operation to aggregate a range vector into an +// instant vector, with optional grouping on specified dimensions. +type AggregateVector struct { + // ID for the node. + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + // Columns to group the data by. If empty, all rows are aggregated into a single result. + GroupBy []*ColumnExpression `protobuf:"bytes,2,rep,name=group_by,json=groupBy,proto3" json:"group_by,omitempty"` + // Aggregation operation to perform over the underlying range vector. + Operation AggregateVectorOp `protobuf:"varint,3,opt,name=operation,proto3,enum=physical.engine.loki.v1.AggregateVectorOp" json:"operation,omitempty"` +} + +func (m *AggregateVector) Reset() { *m = AggregateVector{} } +func (*AggregateVector) ProtoMessage() {} +func (*AggregateVector) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{5} +} +func (m *AggregateVector) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AggregateVector) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AggregateVector.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AggregateVector) XXX_Merge(src proto.Message) { + xxx_messageInfo_AggregateVector.Merge(m, src) +} +func (m *AggregateVector) XXX_Size() int { + return m.Size() +} +func (m *AggregateVector) XXX_DiscardUnknown() { + xxx_messageInfo_AggregateVector.DiscardUnknown(m) +} + +var xxx_messageInfo_AggregateVector proto.InternalMessageInfo + +func (m *AggregateVector) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *AggregateVector) GetGroupBy() []*ColumnExpression { + if m != nil { + return m.GroupBy + } + return nil +} + +func (m *AggregateVector) GetOperation() AggregateVectorOp { + if m != nil { + return m.Operation + } + return AGGREGATE_VECTOR_OP_INVALID +} + +// DataObjScan represents an operation to read the contents of a data object +// section. +type DataObjScan struct { + // ID for the node. + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + // Stored location of the data object to read. + Location string `protobuf:"bytes,2,opt,name=location,proto3" json:"location,omitempty"` + // Section within the data object to read. + Section int64 `protobuf:"varint,3,opt,name=section,proto3" json:"section,omitempty"` + // StreamIDs within the section to read. + StreamIds []int64 `protobuf:"varint,4,rep,packed,name=stream_ids,json=streamIds,proto3" json:"stream_ids,omitempty"` + // Projections are used to limit the columns that are read. + Projections []*ColumnExpression `protobuf:"bytes,5,rep,name=projections,proto3" json:"projections,omitempty"` + // Predicates are used to filter rows to reduce the amount of rows that are + // returned. + Predicates []*Expression `protobuf:"bytes,6,rep,name=predicates,proto3" json:"predicates,omitempty"` + // Sort order for the scan. + SortOrder SortOrder `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3,enum=physical.engine.loki.v1.SortOrder" json:"sort_order,omitempty"` + // Limit of rows to return. + Limit uint32 `protobuf:"varint,8,opt,name=limit,proto3" json:"limit,omitempty"` +} + +func (m *DataObjScan) Reset() { *m = DataObjScan{} } +func (*DataObjScan) ProtoMessage() {} +func (*DataObjScan) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{6} +} +func (m *DataObjScan) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DataObjScan) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DataObjScan.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DataObjScan) XXX_Merge(src proto.Message) { + xxx_messageInfo_DataObjScan.Merge(m, src) +} +func (m *DataObjScan) XXX_Size() int { + return m.Size() +} +func (m *DataObjScan) XXX_DiscardUnknown() { + xxx_messageInfo_DataObjScan.DiscardUnknown(m) +} + +var xxx_messageInfo_DataObjScan proto.InternalMessageInfo + +func (m *DataObjScan) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *DataObjScan) GetLocation() string { + if m != nil { + return m.Location + } + return "" +} + +func (m *DataObjScan) GetSection() int64 { + if m != nil { + return m.Section + } + return 0 +} + +func (m *DataObjScan) GetStreamIds() []int64 { + if m != nil { + return m.StreamIds + } + return nil +} + +func (m *DataObjScan) GetProjections() []*ColumnExpression { + if m != nil { + return m.Projections + } + return nil +} + +func (m *DataObjScan) GetPredicates() []*Expression { + if m != nil { + return m.Predicates + } + return nil +} + +func (m *DataObjScan) GetSortOrder() SortOrder { + if m != nil { + return m.SortOrder + } + return SORT_ORDER_INVALID +} + +func (m *DataObjScan) GetLimit() uint32 { + if m != nil { + return m.Limit + } + return 0 +} + +// Filter represents an operation to filter rows based on a condition. +type Filter struct { + // ID for the node. + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + // Predicates to apply to filter rows. + Predicates []*Expression `protobuf:"bytes,2,rep,name=predicates,proto3" json:"predicates,omitempty"` +} + +func (m *Filter) Reset() { *m = Filter{} } +func (*Filter) ProtoMessage() {} +func (*Filter) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{7} +} +func (m *Filter) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Filter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Filter.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Filter) XXX_Merge(src proto.Message) { + xxx_messageInfo_Filter.Merge(m, src) +} +func (m *Filter) XXX_Size() int { + return m.Size() +} +func (m *Filter) XXX_DiscardUnknown() { + xxx_messageInfo_Filter.DiscardUnknown(m) +} + +var xxx_messageInfo_Filter proto.InternalMessageInfo + +func (m *Filter) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *Filter) GetPredicates() []*Expression { + if m != nil { + return m.Predicates + } + return nil +} + +// Limit represents a limiting operation in the physical plan that applies +// offset and limit to the result set. +type Limit struct { + // ID for the node. + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + // Skip specifies how many initial rows should be skipped. + Skip uint32 `protobuf:"varint,2,opt,name=skip,proto3" json:"skip,omitempty"` + // Fetch specifies how many rows should be returned in total. + Fetch uint32 `protobuf:"varint,3,opt,name=fetch,proto3" json:"fetch,omitempty"` +} + +func (m *Limit) Reset() { *m = Limit{} } +func (*Limit) ProtoMessage() {} +func (*Limit) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{8} +} +func (m *Limit) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Limit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Limit.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Limit) XXX_Merge(src proto.Message) { + xxx_messageInfo_Limit.Merge(m, src) +} +func (m *Limit) XXX_Size() int { + return m.Size() +} +func (m *Limit) XXX_DiscardUnknown() { + xxx_messageInfo_Limit.DiscardUnknown(m) +} + +var xxx_messageInfo_Limit proto.InternalMessageInfo + +func (m *Limit) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *Limit) GetSkip() uint32 { + if m != nil { + return m.Skip + } + return 0 +} + +func (m *Limit) GetFetch() uint32 { + if m != nil { + return m.Fetch + } + return 0 +} + +// Merge represents an operation in the physical plan that merges a sequence of +// inputs into a single output, retaining the order of the inputs. +type Merge struct { + // ID for the node. + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` +} + +func (m *Merge) Reset() { *m = Merge{} } +func (*Merge) ProtoMessage() {} +func (*Merge) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{9} +} +func (m *Merge) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Merge) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Merge.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Merge) XXX_Merge(src proto.Message) { + xxx_messageInfo_Merge.Merge(m, src) +} +func (m *Merge) XXX_Size() int { + return m.Size() +} +func (m *Merge) XXX_DiscardUnknown() { + xxx_messageInfo_Merge.DiscardUnknown(m) +} + +var xxx_messageInfo_Merge proto.InternalMessageInfo + +func (m *Merge) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +// Parse represents an operation to parse a log message into multiple key-value +// pairs. +type Parse struct { + // ID for the node. + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + Operation ParseOp `protobuf:"varint,2,opt,name=operation,proto3,enum=physical.engine.loki.v1.ParseOp" json:"operation,omitempty"` + RequestedKeys []string `protobuf:"bytes,3,rep,name=requested_keys,json=requestedKeys,proto3" json:"requested_keys,omitempty"` +} + +func (m *Parse) Reset() { *m = Parse{} } +func (*Parse) ProtoMessage() {} +func (*Parse) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{10} +} +func (m *Parse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Parse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Parse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Parse) XXX_Merge(src proto.Message) { + xxx_messageInfo_Parse.Merge(m, src) +} +func (m *Parse) XXX_Size() int { + return m.Size() +} +func (m *Parse) XXX_DiscardUnknown() { + xxx_messageInfo_Parse.DiscardUnknown(m) +} + +var xxx_messageInfo_Parse proto.InternalMessageInfo + +func (m *Parse) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *Parse) GetOperation() ParseOp { + if m != nil { + return m.Operation + } + return PARSE_OP_INVALID +} + +func (m *Parse) GetRequestedKeys() []string { + if m != nil { + return m.RequestedKeys + } + return nil +} + +// Projection represents an operation to return a subset of columns from the +// input. +type Projection struct { + // ID for the node. + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + // Expressions is a set of column expressions that are used to drop not needed + // columns that match the column expression, or to expand columns that result + // from the expressions. + Expressions []*Expression `protobuf:"bytes,2,rep,name=Expressions,proto3" json:"Expressions,omitempty"` + All bool `protobuf:"varint,3,opt,name=All,proto3" json:"All,omitempty"` + Expand bool `protobuf:"varint,4,opt,name=Expand,proto3" json:"Expand,omitempty"` + Drop bool `protobuf:"varint,5,opt,name=Drop,proto3" json:"Drop,omitempty"` +} + +func (m *Projection) Reset() { *m = Projection{} } +func (*Projection) ProtoMessage() {} +func (*Projection) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{11} +} +func (m *Projection) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Projection) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Projection.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Projection) XXX_Merge(src proto.Message) { + xxx_messageInfo_Projection.Merge(m, src) +} +func (m *Projection) XXX_Size() int { + return m.Size() +} +func (m *Projection) XXX_DiscardUnknown() { + xxx_messageInfo_Projection.DiscardUnknown(m) +} + +var xxx_messageInfo_Projection proto.InternalMessageInfo + +func (m *Projection) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *Projection) GetExpressions() []*Expression { + if m != nil { + return m.Expressions + } + return nil +} + +func (m *Projection) GetAll() bool { + if m != nil { + return m.All + } + return false +} + +func (m *Projection) GetExpand() bool { + if m != nil { + return m.Expand + } + return false +} + +func (m *Projection) GetDrop() bool { + if m != nil { + return m.Drop + } + return false +} + +// SortMerge represents an operation in the physical plan. It merges a sequence +// of sorted inputs into a single sorted output. +type SortMerge struct { + // ID for the node. + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + // Column defines the column by which the rows should be sorted. This is almost always + // the timestamp column, as it is the column by which DataObjScan results + // are sorted. + Column *ColumnExpression `protobuf:"bytes,2,opt,name=column,proto3" json:"column,omitempty"` + // Order defines how rows for the column are sorted. Must match the sort + // order of the inputs. + Order SortOrder `protobuf:"varint,3,opt,name=order,proto3,enum=physical.engine.loki.v1.SortOrder" json:"order,omitempty"` +} + +func (m *SortMerge) Reset() { *m = SortMerge{} } +func (*SortMerge) ProtoMessage() {} +func (*SortMerge) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{12} +} +func (m *SortMerge) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SortMerge) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SortMerge.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SortMerge) XXX_Merge(src proto.Message) { + xxx_messageInfo_SortMerge.Merge(m, src) +} +func (m *SortMerge) XXX_Size() int { + return m.Size() +} +func (m *SortMerge) XXX_DiscardUnknown() { + xxx_messageInfo_SortMerge.DiscardUnknown(m) +} + +var xxx_messageInfo_SortMerge proto.InternalMessageInfo + +func (m *SortMerge) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *SortMerge) GetColumn() *ColumnExpression { + if m != nil { + return m.Column + } + return nil +} + +func (m *SortMerge) GetOrder() SortOrder { + if m != nil { + return m.Order + } + return SORT_ORDER_INVALID +} + +// ColumnCompat represents a compactibilty operation in the physical plan that +// moves a values from a conflicting metadata column with a label column into a new column suffixed with `_extracted`. +type ColumnCompat struct { + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + // TODO(chaudum): These fields are poorly named. Come up with more descriptive names. + Source ColumnType `protobuf:"varint,2,opt,name=Source,proto3,enum=physical.engine.loki.v1.ColumnType" json:"Source,omitempty"` + Destination ColumnType `protobuf:"varint,3,opt,name=Destination,proto3,enum=physical.engine.loki.v1.ColumnType" json:"Destination,omitempty"` + Collision ColumnType `protobuf:"varint,4,opt,name=Collision,proto3,enum=physical.engine.loki.v1.ColumnType" json:"Collision,omitempty"` +} + +func (m *ColumnCompat) Reset() { *m = ColumnCompat{} } +func (*ColumnCompat) ProtoMessage() {} +func (*ColumnCompat) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{13} +} +func (m *ColumnCompat) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ColumnCompat) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ColumnCompat.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ColumnCompat) XXX_Merge(src proto.Message) { + xxx_messageInfo_ColumnCompat.Merge(m, src) +} +func (m *ColumnCompat) XXX_Size() int { + return m.Size() +} +func (m *ColumnCompat) XXX_DiscardUnknown() { + xxx_messageInfo_ColumnCompat.DiscardUnknown(m) +} + +var xxx_messageInfo_ColumnCompat proto.InternalMessageInfo + +func (m *ColumnCompat) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *ColumnCompat) GetSource() ColumnType { + if m != nil { + return m.Source + } + return COLUMN_TYPE_INVALID +} + +func (m *ColumnCompat) GetDestination() ColumnType { + if m != nil { + return m.Destination + } + return COLUMN_TYPE_INVALID +} + +func (m *ColumnCompat) GetCollision() ColumnType { + if m != nil { + return m.Collision + } + return COLUMN_TYPE_INVALID +} + +type TopK struct { + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + SortBy *ColumnExpression `protobuf:"bytes,2,opt,name=SortBy,proto3" json:"SortBy,omitempty"` + Ascending bool `protobuf:"varint,3,opt,name=Ascending,proto3" json:"Ascending,omitempty"` + NullsFirst bool `protobuf:"varint,4,opt,name=NullsFirst,proto3" json:"NullsFirst,omitempty"` + K int64 `protobuf:"varint,5,opt,name=K,proto3" json:"K,omitempty"` +} + +func (m *TopK) Reset() { *m = TopK{} } +func (*TopK) ProtoMessage() {} +func (*TopK) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{14} +} +func (m *TopK) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TopK) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TopK.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TopK) XXX_Merge(src proto.Message) { + xxx_messageInfo_TopK.Merge(m, src) +} +func (m *TopK) XXX_Size() int { + return m.Size() +} +func (m *TopK) XXX_DiscardUnknown() { + xxx_messageInfo_TopK.DiscardUnknown(m) +} + +var xxx_messageInfo_TopK proto.InternalMessageInfo + +func (m *TopK) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *TopK) GetSortBy() *ColumnExpression { + if m != nil { + return m.SortBy + } + return nil +} + +func (m *TopK) GetAscending() bool { + if m != nil { + return m.Ascending + } + return false +} + +func (m *TopK) GetNullsFirst() bool { + if m != nil { + return m.NullsFirst + } + return false +} + +func (m *TopK) GetK() int64 { + if m != nil { + return m.K + } + return 0 +} + +// ScanSet represents a physical plan operation for reading data from targets. +type ScanSet struct { + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` + // Targets to scan + Targets []*ScanTarget `protobuf:"bytes,2,rep,name=Targets,proto3" json:"Targets,omitempty"` + // Projections are used to limit the columns that are read to the ones + // provided in the column expressions to reduce the amount of data that + // needs to be processed. + Projections []*ColumnExpression `protobuf:"bytes,3,rep,name=Projections,proto3" json:"Projections,omitempty"` + // Predicates are used to filter rows to reduce the amount of rows that are + // returned. Predicates would almost always contain a time range filter to + // only read the logs for the requested time range. + Predicates []*Expression `protobuf:"bytes,4,rep,name=Predicates,proto3" json:"Predicates,omitempty"` +} + +func (m *ScanSet) Reset() { *m = ScanSet{} } +func (*ScanSet) ProtoMessage() {} +func (*ScanSet) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{15} +} +func (m *ScanSet) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ScanSet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ScanSet.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ScanSet) XXX_Merge(src proto.Message) { + xxx_messageInfo_ScanSet.Merge(m, src) +} +func (m *ScanSet) XXX_Size() int { + return m.Size() +} +func (m *ScanSet) XXX_DiscardUnknown() { + xxx_messageInfo_ScanSet.DiscardUnknown(m) +} + +var xxx_messageInfo_ScanSet proto.InternalMessageInfo + +func (m *ScanSet) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func (m *ScanSet) GetTargets() []*ScanTarget { + if m != nil { + return m.Targets + } + return nil +} + +func (m *ScanSet) GetProjections() []*ColumnExpression { + if m != nil { + return m.Projections + } + return nil +} + +func (m *ScanSet) GetPredicates() []*Expression { + if m != nil { + return m.Predicates + } + return nil +} + +// ScanTarget represents a target of a [ScanSet]. +type ScanTarget struct { + Type ScanType `protobuf:"varint,1,opt,name=Type,proto3,enum=physical.engine.loki.v1.ScanType" json:"Type,omitempty"` + // DataObject is non-nil if Type is [ScanTypeDataObject]. Despite DataObjScan + // implementing [Node], the value is not inserted into the graph as a node. + DataObject *DataObjScan `protobuf:"bytes,2,opt,name=DataObject,proto3" json:"DataObject,omitempty"` +} + +func (m *ScanTarget) Reset() { *m = ScanTarget{} } +func (*ScanTarget) ProtoMessage() {} +func (*ScanTarget) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{16} +} +func (m *ScanTarget) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ScanTarget) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ScanTarget.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ScanTarget) XXX_Merge(src proto.Message) { + xxx_messageInfo_ScanTarget.Merge(m, src) +} +func (m *ScanTarget) XXX_Size() int { + return m.Size() +} +func (m *ScanTarget) XXX_DiscardUnknown() { + xxx_messageInfo_ScanTarget.DiscardUnknown(m) +} + +var xxx_messageInfo_ScanTarget proto.InternalMessageInfo + +func (m *ScanTarget) GetType() ScanType { + if m != nil { + return m.Type + } + return SCAN_TYPE_INVALID +} + +func (m *ScanTarget) GetDataObject() *DataObjScan { + if m != nil { + return m.DataObject + } + return nil +} + +// Parallelize represents a hint to the engine to partition and parallelize the +// children branches of the Parallelize and emit results as a single sequence +// with no guaranteed order. +type Parallelize struct { + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` +} + +func (m *Parallelize) Reset() { *m = Parallelize{} } +func (*Parallelize) ProtoMessage() {} +func (*Parallelize) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{17} +} +func (m *Parallelize) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Parallelize) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Parallelize.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Parallelize) XXX_Merge(src proto.Message) { + xxx_messageInfo_Parallelize.Merge(m, src) +} +func (m *Parallelize) XXX_Size() int { + return m.Size() +} +func (m *Parallelize) XXX_DiscardUnknown() { + xxx_messageInfo_Parallelize.DiscardUnknown(m) +} + +var xxx_messageInfo_Parallelize proto.InternalMessageInfo + +func (m *Parallelize) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +// Join represents a join operation in the physical plan. +// For now it is only an inner join on `timestamp`. Will be expanded later. +type Join struct { + Id PlanNodeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id"` +} + +func (m *Join) Reset() { *m = Join{} } +func (*Join) ProtoMessage() {} +func (*Join) Descriptor() ([]byte, []int) { + return fileDescriptor_24be8eac7b1072f5, []int{18} +} +func (m *Join) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Join) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Join.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Join) XXX_Merge(src proto.Message) { + xxx_messageInfo_Join.Merge(m, src) +} +func (m *Join) XXX_Size() int { + return m.Size() +} +func (m *Join) XXX_DiscardUnknown() { + xxx_messageInfo_Join.DiscardUnknown(m) +} + +var xxx_messageInfo_Join proto.InternalMessageInfo + +func (m *Join) GetId() PlanNodeID { + if m != nil { + return m.Id + } + return PlanNodeID{} +} + +func init() { + proto.RegisterEnum("physical.engine.loki.v1.WalkOrder", WalkOrder_name, WalkOrder_value) + proto.RegisterEnum("physical.engine.loki.v1.AggregateRangeOp", AggregateRangeOp_name, AggregateRangeOp_value) + proto.RegisterEnum("physical.engine.loki.v1.AggregateVectorOp", AggregateVectorOp_name, AggregateVectorOp_value) + proto.RegisterEnum("physical.engine.loki.v1.ParseOp", ParseOp_name, ParseOp_value) + proto.RegisterEnum("physical.engine.loki.v1.SortOrder", SortOrder_name, SortOrder_value) + proto.RegisterEnum("physical.engine.loki.v1.ScanType", ScanType_name, ScanType_value) + proto.RegisterType((*Plan)(nil), "physical.engine.loki.v1.Plan") + proto.RegisterType((*PlanEdge)(nil), "physical.engine.loki.v1.PlanEdge") + proto.RegisterType((*PlanNodeID)(nil), "physical.engine.loki.v1.PlanNodeID") + proto.RegisterType((*PlanNode)(nil), "physical.engine.loki.v1.PlanNode") + proto.RegisterType((*AggregateRange)(nil), "physical.engine.loki.v1.AggregateRange") + proto.RegisterType((*AggregateVector)(nil), "physical.engine.loki.v1.AggregateVector") + proto.RegisterType((*DataObjScan)(nil), "physical.engine.loki.v1.DataObjScan") + proto.RegisterType((*Filter)(nil), "physical.engine.loki.v1.Filter") + proto.RegisterType((*Limit)(nil), "physical.engine.loki.v1.Limit") + proto.RegisterType((*Merge)(nil), "physical.engine.loki.v1.Merge") + proto.RegisterType((*Parse)(nil), "physical.engine.loki.v1.Parse") + proto.RegisterType((*Projection)(nil), "physical.engine.loki.v1.Projection") + proto.RegisterType((*SortMerge)(nil), "physical.engine.loki.v1.SortMerge") + proto.RegisterType((*ColumnCompat)(nil), "physical.engine.loki.v1.ColumnCompat") + proto.RegisterType((*TopK)(nil), "physical.engine.loki.v1.TopK") + proto.RegisterType((*ScanSet)(nil), "physical.engine.loki.v1.ScanSet") + proto.RegisterType((*ScanTarget)(nil), "physical.engine.loki.v1.ScanTarget") + proto.RegisterType((*Parallelize)(nil), "physical.engine.loki.v1.Parallelize") + proto.RegisterType((*Join)(nil), "physical.engine.loki.v1.Join") +} + +func init() { + proto.RegisterFile("pkg/engine/internal/planner/physical/physicalpb/physicalpb.proto", fileDescriptor_24be8eac7b1072f5) +} + +var fileDescriptor_24be8eac7b1072f5 = []byte{ + // 1755 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0x4f, 0x73, 0xdb, 0xc6, + 0x15, 0x07, 0x08, 0xfe, 0x7d, 0x92, 0x68, 0x78, 0xeb, 0xd8, 0xb0, 0x12, 0xd3, 0x0a, 0x92, 0x4c, + 0x55, 0x1d, 0xc8, 0x69, 0x9c, 0xfe, 0x49, 0x5b, 0xb7, 0x05, 0x49, 0x98, 0x94, 0x29, 0x91, 0x9c, + 0x25, 0xa5, 0xa4, 0xbd, 0x60, 0x20, 0x60, 0x4d, 0xc3, 0x82, 0x00, 0x14, 0x00, 0x3d, 0x52, 0x4f, + 0x99, 0x5e, 0x9a, 0x5e, 0x3a, 0xb9, 0xf4, 0x1b, 0xf4, 0xd0, 0xf6, 0x6b, 0xf4, 0x92, 0x43, 0x0f, + 0x3e, 0x66, 0x3a, 0x9d, 0x4c, 0x2d, 0xcf, 0x74, 0x7a, 0xcc, 0x47, 0xc8, 0xec, 0x02, 0x14, 0x40, + 0x47, 0x10, 0x45, 0xf3, 0xa2, 0xd9, 0x7d, 0xef, 0xf7, 0x7b, 0x78, 0xfb, 0xde, 0xdb, 0xf7, 0x56, + 0x84, 0x5f, 0x7b, 0xc7, 0x93, 0x06, 0x71, 0x26, 0x96, 0x43, 0x1a, 0x96, 0x13, 0x12, 0xdf, 0xd1, + 0xed, 0x86, 0x67, 0xeb, 0x8e, 0x43, 0xfc, 0x86, 0xf7, 0xf4, 0x2c, 0xb0, 0x0c, 0x2a, 0x88, 0x17, + 0xde, 0x51, 0x6a, 0x59, 0xf7, 0x7c, 0x37, 0x74, 0xd1, 0x9d, 0x99, 0xa4, 0x1e, 0x99, 0xa9, 0xdb, + 0xee, 0xb1, 0x55, 0x7f, 0xfe, 0xc3, 0xcd, 0x5b, 0x13, 0x77, 0xe2, 0x32, 0x4c, 0x83, 0xae, 0x22, + 0xf8, 0xe6, 0xd2, 0x1f, 0x24, 0xa7, 0x9e, 0x4f, 0x82, 0xc0, 0x72, 0x9d, 0xd8, 0xc2, 0xf6, 0x65, + 0x16, 0xa6, 0xa1, 0x65, 0x37, 0xa6, 0xb6, 0x65, 0xb2, 0x3f, 0x11, 0x52, 0x3e, 0x85, 0xfc, 0xd0, + 0xd6, 0x1d, 0xf4, 0x13, 0x28, 0x38, 0xae, 0x49, 0x02, 0x89, 0xdf, 0x12, 0xb6, 0xd7, 0x3e, 0x7c, + 0xb7, 0x9e, 0xe1, 0x72, 0x9d, 0xa2, 0xfb, 0xae, 0x49, 0x70, 0x84, 0xa7, 0x44, 0x62, 0x4e, 0x48, + 0x20, 0xe5, 0xae, 0x41, 0x54, 0xcd, 0x09, 0xc1, 0x11, 0x5e, 0xfe, 0x33, 0x0f, 0xe5, 0x99, 0x0c, + 0x29, 0x50, 0xf4, 0x74, 0x9f, 0x38, 0xa1, 0xc4, 0x6f, 0xf1, 0xdb, 0x6b, 0x1f, 0xbe, 0xb7, 0xf0, + 0xfb, 0xbb, 0xed, 0x66, 0xfe, 0xcb, 0xaf, 0xef, 0x73, 0x38, 0x26, 0xa2, 0x5f, 0x41, 0xc1, 0x78, + 0x6a, 0xd9, 0xa6, 0x94, 0x5b, 0xd6, 0x42, 0xc4, 0x93, 0xff, 0xc0, 0x03, 0x24, 0x3a, 0x14, 0x42, + 0xe1, 0xb9, 0x6e, 0x4f, 0x49, 0xec, 0xd1, 0x9d, 0x3a, 0x8b, 0xda, 0x85, 0x11, 0x1a, 0xbd, 0x83, + 0xbd, 0xdd, 0x76, 0x53, 0xa5, 0x36, 0xfe, 0xfd, 0xf5, 0xfd, 0x87, 0x13, 0x2b, 0x7c, 0x3a, 0x3d, + 0xaa, 0x1b, 0xee, 0x49, 0x63, 0xe2, 0xeb, 0x4f, 0x74, 0x47, 0x6f, 0x50, 0x74, 0xe3, 0xf9, 0x83, + 0xc6, 0x95, 0xe9, 0xa8, 0x53, 0x33, 0x38, 0xfa, 0x98, 0xfc, 0x8f, 0x52, 0x14, 0x15, 0xea, 0x04, + 0xc2, 0x70, 0x43, 0x9f, 0x4c, 0x7c, 0x32, 0xd1, 0x43, 0xa2, 0xf9, 0xba, 0x33, 0x99, 0x39, 0xf3, + 0xfd, 0xcc, 0xc3, 0x29, 0x33, 0x3c, 0xa6, 0xf0, 0x2e, 0x87, 0xab, 0xfa, 0x9c, 0x04, 0x1d, 0x80, + 0x98, 0xd8, 0x7c, 0x4e, 0x8c, 0xd0, 0xf5, 0xe3, 0x88, 0x6d, 0x2f, 0x36, 0x7a, 0xc8, 0xf0, 0x5d, + 0x0e, 0x27, 0x7e, 0x45, 0x22, 0xf4, 0x33, 0xc8, 0x07, 0x86, 0xee, 0x48, 0x02, 0x33, 0xf5, 0x7e, + 0xa6, 0xa9, 0xb6, 0x1e, 0xea, 0x83, 0xa3, 0x67, 0x23, 0x43, 0x77, 0xba, 0x1c, 0x66, 0x1c, 0xf4, + 0x31, 0x14, 0x9f, 0x58, 0x76, 0x48, 0x7c, 0x29, 0xcf, 0xd8, 0xf7, 0x33, 0xd9, 0x8f, 0x18, 0xac, + 0xcb, 0xe1, 0x98, 0x80, 0x7e, 0x0c, 0x05, 0xdb, 0x3a, 0xb1, 0x42, 0xa9, 0xc0, 0x98, 0xb5, 0x4c, + 0xe6, 0x1e, 0x45, 0x75, 0x39, 0x1c, 0xc1, 0x29, 0xef, 0x84, 0xf8, 0x13, 0x22, 0x15, 0x17, 0xf0, + 0xf6, 0x29, 0x8a, 0xf2, 0x18, 0x9c, 0xf2, 0x3c, 0xdd, 0x0f, 0x88, 0x54, 0x5a, 0xc0, 0x1b, 0x52, + 0x14, 0xe5, 0x31, 0x38, 0x52, 0x01, 0x3c, 0xdf, 0x7d, 0x46, 0x8c, 0xd0, 0x72, 0x1d, 0xa9, 0xbc, + 0xa8, 0x42, 0x2f, 0xa0, 0x5d, 0x0e, 0xa7, 0x88, 0xa8, 0x05, 0x10, 0xb8, 0x7e, 0xa8, 0x45, 0xbe, + 0x57, 0x98, 0x19, 0x39, 0xd3, 0xcc, 0xc8, 0xf5, 0xc3, 0x99, 0xff, 0x95, 0x60, 0xb6, 0x41, 0x7b, + 0xb0, 0x61, 0xb8, 0xf6, 0xf4, 0xc4, 0xd1, 0x0c, 0xf7, 0xc4, 0xd3, 0x43, 0x09, 0x98, 0x9d, 0x0f, + 0x32, 0xed, 0xb4, 0x18, 0xba, 0xc5, 0xc0, 0x5d, 0x0e, 0xaf, 0x1b, 0xa9, 0x3d, 0x7a, 0x08, 0x65, + 0x9a, 0x44, 0x2d, 0x20, 0xa1, 0xb4, 0xc6, 0x0c, 0x6d, 0x65, 0x3b, 0x64, 0xe8, 0xce, 0x88, 0x50, + 0x1b, 0xa5, 0x20, 0x5a, 0xa2, 0x8f, 0xa0, 0x10, 0xba, 0x9e, 0x76, 0x2c, 0xad, 0x33, 0xee, 0xbd, + 0x4c, 0xee, 0xd8, 0xf5, 0x7a, 0xb4, 0x62, 0x42, 0xd7, 0xeb, 0xa1, 0x2e, 0xac, 0x79, 0xba, 0xaf, + 0xdb, 0x36, 0xb1, 0xad, 0xdf, 0x13, 0x69, 0x63, 0x41, 0xd1, 0x0d, 0x13, 0x6c, 0x97, 0xc3, 0x69, + 0x2a, 0x7a, 0x00, 0xf9, 0x67, 0xae, 0xe5, 0x48, 0xd5, 0x05, 0x9f, 0x7f, 0xec, 0x5a, 0xac, 0x60, + 0x29, 0xb8, 0x59, 0x84, 0xfc, 0xb1, 0xe5, 0x98, 0xf2, 0xff, 0x72, 0x50, 0x9d, 0xbf, 0x70, 0xe8, + 0x63, 0xc8, 0x59, 0xe6, 0xf2, 0x4d, 0x2c, 0x67, 0x99, 0x68, 0x0f, 0xd6, 0x3d, 0xdd, 0x0f, 0x2d, + 0x9a, 0x69, 0xed, 0xe8, 0x2c, 0x6e, 0xa8, 0x3f, 0x58, 0x90, 0x16, 0xf5, 0xa2, 0xf7, 0xb3, 0x83, + 0x45, 0xf4, 0xe6, 0x19, 0xea, 0x40, 0xc5, 0xf5, 0x88, 0xaf, 0xb3, 0x82, 0xa3, 0xb7, 0xb2, 0x7a, + 0x85, 0xa9, 0xf9, 0x43, 0x0c, 0x3c, 0x9c, 0x70, 0xd1, 0x36, 0x88, 0x41, 0xa8, 0xfb, 0xa1, 0x36, + 0x75, 0xac, 0x53, 0xcd, 0xd1, 0x1d, 0x37, 0x60, 0xf7, 0x54, 0xc0, 0x55, 0x26, 0x3f, 0x70, 0xac, + 0xd3, 0x3e, 0x95, 0xa2, 0xf7, 0xa1, 0x4a, 0x1c, 0x33, 0x8d, 0x2b, 0x30, 0xdc, 0x3a, 0x71, 0xcc, + 0x04, 0x75, 0x07, 0x4a, 0x41, 0x48, 0x3c, 0xcd, 0x09, 0xd8, 0xe5, 0x13, 0x70, 0x91, 0x6e, 0xfb, + 0x01, 0xba, 0x0b, 0x65, 0xd6, 0xe3, 0xa8, 0xa6, 0xc4, 0x34, 0x25, 0xb6, 0xef, 0x07, 0xf2, 0x7f, + 0x78, 0xb8, 0xf1, 0x5a, 0x13, 0x5a, 0x25, 0xd2, 0x6d, 0x28, 0x4f, 0x7c, 0x77, 0xea, 0xbd, 0x51, + 0x94, 0x4b, 0x8c, 0xda, 0x3c, 0x43, 0xdd, 0xef, 0x46, 0x78, 0xe7, 0xba, 0x2d, 0x74, 0x2e, 0xc4, + 0xf2, 0xe7, 0x02, 0xac, 0xa5, 0x1a, 0xe3, 0x2a, 0x47, 0xdb, 0x84, 0xb2, 0xed, 0x1a, 0x91, 0x4f, + 0xb4, 0xad, 0x57, 0xf0, 0xc5, 0x1e, 0x49, 0x50, 0x0a, 0xe2, 0x0e, 0x24, 0x44, 0xf1, 0x8d, 0xb7, + 0xe8, 0x1e, 0x40, 0x10, 0xfa, 0x44, 0x3f, 0xd1, 0x2c, 0x93, 0x66, 0x57, 0xd8, 0x16, 0x70, 0x25, + 0x92, 0xec, 0x9a, 0x01, 0xea, 0xc1, 0x5a, 0xd2, 0x84, 0x68, 0x56, 0x97, 0x2e, 0xcc, 0x84, 0x4d, + 0x7b, 0x98, 0xe7, 0x13, 0xd3, 0x32, 0xf4, 0x90, 0xd0, 0x12, 0x10, 0xae, 0x3c, 0x64, 0xca, 0x4a, + 0x8a, 0x86, 0x94, 0xb8, 0x11, 0xba, 0xbe, 0x49, 0x7c, 0x56, 0x2d, 0xd5, 0x05, 0x8d, 0x70, 0x40, + 0x91, 0x51, 0x1b, 0x64, 0x4b, 0x74, 0x6b, 0x36, 0x3a, 0x68, 0x37, 0xde, 0x88, 0x07, 0x83, 0xfc, + 0x39, 0x0f, 0xc5, 0x68, 0xca, 0xac, 0x92, 0x85, 0xf9, 0x33, 0xe6, 0xde, 0xe8, 0x8c, 0xb2, 0x0d, + 0x05, 0x36, 0xb5, 0x56, 0x71, 0x04, 0x41, 0x3e, 0x38, 0xb6, 0x3c, 0x56, 0x0a, 0x1b, 0x98, 0xad, + 0xe9, 0xc1, 0x9f, 0x90, 0xd0, 0x78, 0xca, 0x8a, 0x60, 0x03, 0x47, 0x1b, 0xb9, 0x09, 0x85, 0x68, + 0x3c, 0xbc, 0xf9, 0xd7, 0xe4, 0xbf, 0xf3, 0x50, 0x60, 0x83, 0x6f, 0x15, 0x97, 0x7f, 0x99, 0xbe, + 0x56, 0x39, 0x96, 0xd9, 0xad, 0xab, 0xc7, 0xec, 0x7c, 0xbf, 0xfa, 0x00, 0xaa, 0x3e, 0xf9, 0xdd, + 0x94, 0x04, 0x21, 0x31, 0xb5, 0x63, 0x72, 0x16, 0x48, 0xc2, 0x96, 0xb0, 0x5d, 0xc1, 0x1b, 0x17, + 0xd2, 0x1e, 0x39, 0x0b, 0xe4, 0x7f, 0xd1, 0xd7, 0x5e, 0x32, 0x59, 0x57, 0x70, 0x58, 0x85, 0xb5, + 0x24, 0x83, 0x4b, 0x65, 0x3b, 0xcd, 0x43, 0x22, 0x08, 0x8a, 0x6d, 0xb3, 0xa4, 0x94, 0x31, 0x5d, + 0xa2, 0xdb, 0x50, 0x54, 0x4f, 0x3d, 0xdd, 0x31, 0x59, 0xbf, 0x2d, 0xe3, 0x78, 0x47, 0x93, 0xda, + 0xf6, 0x5d, 0x8f, 0x75, 0xd7, 0x32, 0x66, 0x6b, 0xf9, 0x9f, 0x3c, 0x54, 0x2e, 0xe6, 0xfd, 0x2a, + 0xa7, 0x51, 0xa0, 0x18, 0xcd, 0xf7, 0xf8, 0x55, 0xb8, 0xc4, 0x35, 0x8f, 0x89, 0xe8, 0xa7, 0x50, + 0x88, 0xee, 0xa5, 0x70, 0xed, 0x7b, 0x19, 0x11, 0xe4, 0x2f, 0x72, 0xb0, 0x9e, 0x7e, 0x6d, 0xac, + 0x72, 0x90, 0x9f, 0x43, 0x71, 0xe4, 0x4e, 0x7d, 0x83, 0xc4, 0x45, 0xf4, 0xde, 0x82, 0x83, 0x8c, + 0xcf, 0x3c, 0x82, 0x63, 0x0a, 0xcd, 0x69, 0x9b, 0x04, 0xa1, 0xe5, 0xa4, 0xbb, 0xfb, 0xb5, 0x2c, + 0xa4, 0x79, 0x48, 0x81, 0x4a, 0xcb, 0xb5, 0x6d, 0x8b, 0x86, 0x87, 0x25, 0xf1, 0x9a, 0x46, 0x12, + 0x96, 0xfc, 0x82, 0x87, 0x3c, 0x7d, 0xfb, 0xac, 0x98, 0x53, 0x1a, 0xea, 0xe6, 0xd9, 0x1b, 0xe4, + 0x34, 0x22, 0xa2, 0x77, 0xa0, 0xa2, 0x04, 0x06, 0x71, 0x4c, 0xcb, 0x99, 0xc4, 0x35, 0x9a, 0x08, + 0x50, 0x0d, 0xa0, 0x3f, 0xb5, 0xed, 0xe0, 0x91, 0xe5, 0x07, 0x61, 0x5c, 0xad, 0x29, 0x09, 0x5a, + 0x07, 0xbe, 0x17, 0x3f, 0x06, 0xf8, 0x9e, 0xfc, 0x97, 0x1c, 0x94, 0xe2, 0xa7, 0xe0, 0x2a, 0xa7, + 0x7a, 0x08, 0xa5, 0xb1, 0xee, 0x4f, 0x48, 0xb8, 0xf8, 0xce, 0xd1, 0xaf, 0x45, 0x58, 0x3c, 0xe3, + 0xd0, 0xa1, 0x36, 0x4c, 0x0d, 0x35, 0x61, 0xe9, 0xa1, 0x36, 0x9c, 0x1f, 0x6a, 0xc3, 0xa4, 0xe1, + 0xe7, 0x97, 0x68, 0xf8, 0x09, 0x4d, 0xfe, 0x13, 0x0f, 0x90, 0x78, 0x8a, 0x7e, 0x04, 0x79, 0x5a, + 0x0c, 0x2c, 0x38, 0xd5, 0x2b, 0xfe, 0xb1, 0x66, 0x14, 0x5a, 0x35, 0x0c, 0x8e, 0xda, 0x00, 0xf1, + 0x5b, 0x82, 0x18, 0x61, 0x9c, 0xf0, 0x6b, 0xfd, 0x3f, 0x86, 0x53, 0x3c, 0xb9, 0x0b, 0x6b, 0xa9, + 0x57, 0xf3, 0x2a, 0x43, 0x41, 0x81, 0x3c, 0x7d, 0x3c, 0xaf, 0x60, 0x62, 0xe7, 0x23, 0xa8, 0x7c, + 0xa2, 0xdb, 0xc7, 0xd1, 0xdc, 0x46, 0x50, 0x1d, 0x62, 0x55, 0x1b, 0xe0, 0xb6, 0x8a, 0xb5, 0x4f, + 0x94, 0xbd, 0x9e, 0xc8, 0xa1, 0xef, 0xc1, 0x8d, 0xe1, 0x60, 0x34, 0x4e, 0x0b, 0xf9, 0x9d, 0xbf, + 0xf2, 0x20, 0xbe, 0xfe, 0xb0, 0x45, 0x35, 0xd8, 0x54, 0x3a, 0x1d, 0xac, 0x76, 0x94, 0xb1, 0xaa, + 0x61, 0xa5, 0xdf, 0x51, 0xb5, 0xc1, 0x50, 0xdb, 0xed, 0x1f, 0x2a, 0x7b, 0xbb, 0x6d, 0x91, 0x43, + 0xef, 0x80, 0x74, 0x89, 0xbe, 0x35, 0x38, 0xe8, 0x8f, 0x45, 0x1e, 0x6d, 0xc2, 0xed, 0x4b, 0xb4, + 0xa3, 0x83, 0x7d, 0x31, 0x97, 0xa1, 0xdb, 0x57, 0x3e, 0x15, 0x85, 0x2c, 0xdd, 0x6e, 0x5f, 0xcc, + 0xef, 0xfc, 0x51, 0x80, 0x9b, 0xdf, 0x79, 0x1d, 0xa2, 0xfb, 0xf0, 0x76, 0xc2, 0x38, 0x54, 0x5b, + 0xe3, 0x01, 0x9e, 0x77, 0xf4, 0x6d, 0xb8, 0x73, 0x19, 0x80, 0xfa, 0xc2, 0x67, 0x29, 0xa9, 0x33, + 0xb9, 0x4c, 0xe5, 0x6e, 0x5f, 0x14, 0xd0, 0x3d, 0xb8, 0x7b, 0x99, 0x32, 0x0a, 0x40, 0x3e, 0x8b, + 0xab, 0x1c, 0x76, 0xc4, 0xc2, 0x7c, 0x6c, 0x53, 0x2e, 0x8d, 0xdb, 0x6d, 0xf5, 0x50, 0x2c, 0x5e, + 0xa1, 0x3f, 0x54, 0xb0, 0x58, 0xca, 0x3a, 0x73, 0x73, 0x30, 0x1e, 0x0f, 0xf6, 0x7b, 0x62, 0x79, + 0x3e, 0x39, 0x09, 0x60, 0x3c, 0x18, 0xf6, 0xc4, 0x4a, 0x96, 0x76, 0x34, 0xc0, 0x63, 0x11, 0xd0, + 0xbb, 0x70, 0x2f, 0x4b, 0xab, 0xb5, 0xd5, 0x51, 0x4b, 0x5c, 0xdb, 0xe9, 0x40, 0x29, 0x7e, 0x4f, + 0xa0, 0x5b, 0x20, 0x0e, 0x15, 0x3c, 0x7a, 0xad, 0x38, 0x68, 0x99, 0xcd, 0xa4, 0x7b, 0x83, 0xce, + 0xa3, 0x7d, 0x5a, 0x13, 0x37, 0x61, 0xe3, 0x42, 0xf8, 0x78, 0x34, 0xe8, 0x8b, 0xb9, 0x9d, 0x4f, + 0xa3, 0x59, 0x1c, 0xd5, 0xeb, 0x6d, 0x40, 0xec, 0x23, 0x51, 0x6d, 0x26, 0xc6, 0x24, 0xb8, 0x95, + 0x92, 0x2b, 0xa3, 0x96, 0xda, 0x6f, 0xef, 0xf6, 0x3b, 0x22, 0x8f, 0xee, 0xc2, 0x5b, 0x29, 0x0d, + 0x75, 0x2e, 0x56, 0xe5, 0x76, 0x7e, 0x01, 0xe5, 0xd9, 0x75, 0x47, 0x6f, 0xc1, 0xcd, 0x51, 0x4b, + 0xe9, 0x6b, 0xe3, 0xdf, 0x0c, 0xd5, 0x94, 0x5d, 0xca, 0xbe, 0x10, 0xb7, 0x95, 0xb1, 0xa2, 0x0d, + 0x9a, 0x8f, 0xd5, 0xd6, 0x58, 0xe4, 0x9b, 0x9f, 0xf1, 0x2f, 0x5e, 0xd6, 0xb8, 0xaf, 0x5e, 0xd6, + 0xb8, 0x6f, 0x5e, 0xd6, 0xf8, 0xcf, 0xce, 0x6b, 0xfc, 0xdf, 0xce, 0x6b, 0xfc, 0x97, 0xe7, 0x35, + 0xfe, 0xc5, 0x79, 0x8d, 0xff, 0xef, 0x79, 0x8d, 0xff, 0xff, 0x79, 0x8d, 0xfb, 0xe6, 0xbc, 0xc6, + 0x7f, 0xf1, 0xaa, 0xc6, 0xbd, 0x78, 0x55, 0xe3, 0xbe, 0x7a, 0x55, 0xe3, 0x7e, 0xfb, 0x78, 0xc9, + 0x5f, 0xb6, 0xae, 0xf8, 0xa9, 0x72, 0xc8, 0x1f, 0x15, 0xd9, 0x0f, 0x8f, 0x0f, 0xbe, 0x0d, 0x00, + 0x00, 0xff, 0xff, 0xce, 0x24, 0x3f, 0x1c, 0x57, 0x15, 0x00, 0x00, +} + +func (x WalkOrder) String() string { + s, ok := WalkOrder_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (x AggregateRangeOp) String() string { + s, ok := AggregateRangeOp_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (x AggregateVectorOp) String() string { + s, ok := AggregateVectorOp_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (x ParseOp) String() string { + s, ok := ParseOp_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (x SortOrder) String() string { + s, ok := SortOrder_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (x ScanType) String() string { + s, ok := ScanType_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (this *Plan) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Plan) + if !ok { + that2, ok := that.(Plan) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.Nodes) != len(that1.Nodes) { + return false + } + for i := range this.Nodes { + if !this.Nodes[i].Equal(that1.Nodes[i]) { + return false + } + } + if len(this.Edges) != len(that1.Edges) { + return false + } + for i := range this.Edges { + if !this.Edges[i].Equal(that1.Edges[i]) { + return false + } + } + return true +} +func (this *PlanEdge) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanEdge) + if !ok { + that2, ok := that.(PlanEdge) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Parent.Equal(&that1.Parent) { + return false + } + if !this.Child.Equal(&that1.Child) { + return false + } + return true +} +func (this *PlanNodeID) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNodeID) + if !ok { + that2, ok := that.(PlanNodeID) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Value.Equal(that1.Value) { + return false + } + return true +} +func (this *PlanNode) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode) + if !ok { + that2, ok := that.(PlanNode) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if that1.Kind == nil { + if this.Kind != nil { + return false + } + } else if this.Kind == nil { + return false + } else if !this.Kind.Equal(that1.Kind) { + return false + } + return true +} +func (this *PlanNode_AggregateRange) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_AggregateRange) + if !ok { + that2, ok := that.(PlanNode_AggregateRange) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.AggregateRange.Equal(that1.AggregateRange) { + return false + } + return true +} +func (this *PlanNode_AggregateVector) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_AggregateVector) + if !ok { + that2, ok := that.(PlanNode_AggregateVector) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.AggregateVector.Equal(that1.AggregateVector) { + return false + } + return true +} +func (this *PlanNode_Scan) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_Scan) + if !ok { + that2, ok := that.(PlanNode_Scan) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Scan.Equal(that1.Scan) { + return false + } + return true +} +func (this *PlanNode_Filter) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_Filter) + if !ok { + that2, ok := that.(PlanNode_Filter) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Filter.Equal(that1.Filter) { + return false + } + return true +} +func (this *PlanNode_Limit) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_Limit) + if !ok { + that2, ok := that.(PlanNode_Limit) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Limit.Equal(that1.Limit) { + return false + } + return true +} +func (this *PlanNode_Merge) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_Merge) + if !ok { + that2, ok := that.(PlanNode_Merge) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Merge.Equal(that1.Merge) { + return false + } + return true +} +func (this *PlanNode_Parse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_Parse) + if !ok { + that2, ok := that.(PlanNode_Parse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Parse.Equal(that1.Parse) { + return false + } + return true +} +func (this *PlanNode_Projection) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_Projection) + if !ok { + that2, ok := that.(PlanNode_Projection) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Projection.Equal(that1.Projection) { + return false + } + return true +} +func (this *PlanNode_SortMerge) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_SortMerge) + if !ok { + that2, ok := that.(PlanNode_SortMerge) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.SortMerge.Equal(that1.SortMerge) { + return false + } + return true +} +func (this *PlanNode_ColumnCompat) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_ColumnCompat) + if !ok { + that2, ok := that.(PlanNode_ColumnCompat) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.ColumnCompat.Equal(that1.ColumnCompat) { + return false + } + return true +} +func (this *PlanNode_ScanSet) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_ScanSet) + if !ok { + that2, ok := that.(PlanNode_ScanSet) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.ScanSet.Equal(that1.ScanSet) { + return false + } + return true +} +func (this *PlanNode_TopK) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_TopK) + if !ok { + that2, ok := that.(PlanNode_TopK) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.TopK.Equal(that1.TopK) { + return false + } + return true +} +func (this *PlanNode_Parallelize) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_Parallelize) + if !ok { + that2, ok := that.(PlanNode_Parallelize) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Parallelize.Equal(that1.Parallelize) { + return false + } + return true +} +func (this *PlanNode_Join) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PlanNode_Join) + if !ok { + that2, ok := that.(PlanNode_Join) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Join.Equal(that1.Join) { + return false + } + return true +} +func (this *AggregateRange) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*AggregateRange) + if !ok { + that2, ok := that.(AggregateRange) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if len(this.PartitionBy) != len(that1.PartitionBy) { + return false + } + for i := range this.PartitionBy { + if !this.PartitionBy[i].Equal(that1.PartitionBy[i]) { + return false + } + } + if this.Operation != that1.Operation { + return false + } + if this.StartUnixNanos != that1.StartUnixNanos { + return false + } + if this.EndUnixNanos != that1.EndUnixNanos { + return false + } + if this.StepNs != that1.StepNs { + return false + } + if this.RangeNs != that1.RangeNs { + return false + } + return true +} +func (this *AggregateVector) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*AggregateVector) + if !ok { + that2, ok := that.(AggregateVector) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if len(this.GroupBy) != len(that1.GroupBy) { + return false + } + for i := range this.GroupBy { + if !this.GroupBy[i].Equal(that1.GroupBy[i]) { + return false + } + } + if this.Operation != that1.Operation { + return false + } + return true +} +func (this *DataObjScan) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*DataObjScan) + if !ok { + that2, ok := that.(DataObjScan) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if this.Location != that1.Location { + return false + } + if this.Section != that1.Section { + return false + } + if len(this.StreamIds) != len(that1.StreamIds) { + return false + } + for i := range this.StreamIds { + if this.StreamIds[i] != that1.StreamIds[i] { + return false + } + } + if len(this.Projections) != len(that1.Projections) { + return false + } + for i := range this.Projections { + if !this.Projections[i].Equal(that1.Projections[i]) { + return false + } + } + if len(this.Predicates) != len(that1.Predicates) { + return false + } + for i := range this.Predicates { + if !this.Predicates[i].Equal(that1.Predicates[i]) { + return false + } + } + if this.SortOrder != that1.SortOrder { + return false + } + if this.Limit != that1.Limit { + return false + } + return true +} +func (this *Filter) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Filter) + if !ok { + that2, ok := that.(Filter) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if len(this.Predicates) != len(that1.Predicates) { + return false + } + for i := range this.Predicates { + if !this.Predicates[i].Equal(that1.Predicates[i]) { + return false + } + } + return true +} +func (this *Limit) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Limit) + if !ok { + that2, ok := that.(Limit) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if this.Skip != that1.Skip { + return false + } + if this.Fetch != that1.Fetch { + return false + } + return true +} +func (this *Merge) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Merge) + if !ok { + that2, ok := that.(Merge) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + return true +} +func (this *Parse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Parse) + if !ok { + that2, ok := that.(Parse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if this.Operation != that1.Operation { + return false + } + if len(this.RequestedKeys) != len(that1.RequestedKeys) { + return false + } + for i := range this.RequestedKeys { + if this.RequestedKeys[i] != that1.RequestedKeys[i] { + return false + } + } + return true +} +func (this *Projection) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Projection) + if !ok { + that2, ok := that.(Projection) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if len(this.Expressions) != len(that1.Expressions) { + return false + } + for i := range this.Expressions { + if !this.Expressions[i].Equal(that1.Expressions[i]) { + return false + } + } + if this.All != that1.All { + return false + } + if this.Expand != that1.Expand { + return false + } + if this.Drop != that1.Drop { + return false + } + return true +} +func (this *SortMerge) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*SortMerge) + if !ok { + that2, ok := that.(SortMerge) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if !this.Column.Equal(that1.Column) { + return false + } + if this.Order != that1.Order { + return false + } + return true +} +func (this *ColumnCompat) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ColumnCompat) + if !ok { + that2, ok := that.(ColumnCompat) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if this.Source != that1.Source { + return false + } + if this.Destination != that1.Destination { + return false + } + if this.Collision != that1.Collision { + return false + } + return true +} +func (this *TopK) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*TopK) + if !ok { + that2, ok := that.(TopK) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if !this.SortBy.Equal(that1.SortBy) { + return false + } + if this.Ascending != that1.Ascending { + return false + } + if this.NullsFirst != that1.NullsFirst { + return false + } + if this.K != that1.K { + return false + } + return true +} +func (this *ScanSet) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ScanSet) + if !ok { + that2, ok := that.(ScanSet) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + if len(this.Targets) != len(that1.Targets) { + return false + } + for i := range this.Targets { + if !this.Targets[i].Equal(that1.Targets[i]) { + return false + } + } + if len(this.Projections) != len(that1.Projections) { + return false + } + for i := range this.Projections { + if !this.Projections[i].Equal(that1.Projections[i]) { + return false + } + } + if len(this.Predicates) != len(that1.Predicates) { + return false + } + for i := range this.Predicates { + if !this.Predicates[i].Equal(that1.Predicates[i]) { + return false + } + } + return true +} +func (this *ScanTarget) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ScanTarget) + if !ok { + that2, ok := that.(ScanTarget) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Type != that1.Type { + return false + } + if !this.DataObject.Equal(that1.DataObject) { + return false + } + return true +} +func (this *Parallelize) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Parallelize) + if !ok { + that2, ok := that.(Parallelize) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + return true +} +func (this *Join) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Join) + if !ok { + that2, ok := that.(Join) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Id.Equal(&that1.Id) { + return false + } + return true +} +func (this *Plan) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&physicalpb.Plan{") + if this.Nodes != nil { + s = append(s, "Nodes: "+fmt.Sprintf("%#v", this.Nodes)+",\n") + } + if this.Edges != nil { + s = append(s, "Edges: "+fmt.Sprintf("%#v", this.Edges)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *PlanEdge) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&physicalpb.PlanEdge{") + s = append(s, "Parent: "+strings.Replace(this.Parent.GoString(), `&`, ``, 1)+",\n") + s = append(s, "Child: "+strings.Replace(this.Child.GoString(), `&`, ``, 1)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *PlanNodeID) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.PlanNodeID{") + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *PlanNode) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 18) + s = append(s, "&physicalpb.PlanNode{") + if this.Kind != nil { + s = append(s, "Kind: "+fmt.Sprintf("%#v", this.Kind)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *PlanNode_AggregateRange) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_AggregateRange{` + + `AggregateRange:` + fmt.Sprintf("%#v", this.AggregateRange) + `}`}, ", ") + return s +} +func (this *PlanNode_AggregateVector) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_AggregateVector{` + + `AggregateVector:` + fmt.Sprintf("%#v", this.AggregateVector) + `}`}, ", ") + return s +} +func (this *PlanNode_Scan) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_Scan{` + + `Scan:` + fmt.Sprintf("%#v", this.Scan) + `}`}, ", ") + return s +} +func (this *PlanNode_Filter) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_Filter{` + + `Filter:` + fmt.Sprintf("%#v", this.Filter) + `}`}, ", ") + return s +} +func (this *PlanNode_Limit) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_Limit{` + + `Limit:` + fmt.Sprintf("%#v", this.Limit) + `}`}, ", ") + return s +} +func (this *PlanNode_Merge) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_Merge{` + + `Merge:` + fmt.Sprintf("%#v", this.Merge) + `}`}, ", ") + return s +} +func (this *PlanNode_Parse) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_Parse{` + + `Parse:` + fmt.Sprintf("%#v", this.Parse) + `}`}, ", ") + return s +} +func (this *PlanNode_Projection) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_Projection{` + + `Projection:` + fmt.Sprintf("%#v", this.Projection) + `}`}, ", ") + return s +} +func (this *PlanNode_SortMerge) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_SortMerge{` + + `SortMerge:` + fmt.Sprintf("%#v", this.SortMerge) + `}`}, ", ") + return s +} +func (this *PlanNode_ColumnCompat) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_ColumnCompat{` + + `ColumnCompat:` + fmt.Sprintf("%#v", this.ColumnCompat) + `}`}, ", ") + return s +} +func (this *PlanNode_ScanSet) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_ScanSet{` + + `ScanSet:` + fmt.Sprintf("%#v", this.ScanSet) + `}`}, ", ") + return s +} +func (this *PlanNode_TopK) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_TopK{` + + `TopK:` + fmt.Sprintf("%#v", this.TopK) + `}`}, ", ") + return s +} +func (this *PlanNode_Parallelize) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_Parallelize{` + + `Parallelize:` + fmt.Sprintf("%#v", this.Parallelize) + `}`}, ", ") + return s +} +func (this *PlanNode_Join) GoString() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&physicalpb.PlanNode_Join{` + + `Join:` + fmt.Sprintf("%#v", this.Join) + `}`}, ", ") + return s +} +func (this *AggregateRange) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 11) + s = append(s, "&physicalpb.AggregateRange{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + if this.PartitionBy != nil { + s = append(s, "PartitionBy: "+fmt.Sprintf("%#v", this.PartitionBy)+",\n") + } + s = append(s, "Operation: "+fmt.Sprintf("%#v", this.Operation)+",\n") + s = append(s, "StartUnixNanos: "+fmt.Sprintf("%#v", this.StartUnixNanos)+",\n") + s = append(s, "EndUnixNanos: "+fmt.Sprintf("%#v", this.EndUnixNanos)+",\n") + s = append(s, "StepNs: "+fmt.Sprintf("%#v", this.StepNs)+",\n") + s = append(s, "RangeNs: "+fmt.Sprintf("%#v", this.RangeNs)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *AggregateVector) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 7) + s = append(s, "&physicalpb.AggregateVector{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + if this.GroupBy != nil { + s = append(s, "GroupBy: "+fmt.Sprintf("%#v", this.GroupBy)+",\n") + } + s = append(s, "Operation: "+fmt.Sprintf("%#v", this.Operation)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *DataObjScan) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 12) + s = append(s, "&physicalpb.DataObjScan{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + s = append(s, "Location: "+fmt.Sprintf("%#v", this.Location)+",\n") + s = append(s, "Section: "+fmt.Sprintf("%#v", this.Section)+",\n") + s = append(s, "StreamIds: "+fmt.Sprintf("%#v", this.StreamIds)+",\n") + if this.Projections != nil { + s = append(s, "Projections: "+fmt.Sprintf("%#v", this.Projections)+",\n") + } + if this.Predicates != nil { + s = append(s, "Predicates: "+fmt.Sprintf("%#v", this.Predicates)+",\n") + } + s = append(s, "SortOrder: "+fmt.Sprintf("%#v", this.SortOrder)+",\n") + s = append(s, "Limit: "+fmt.Sprintf("%#v", this.Limit)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Filter) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&physicalpb.Filter{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + if this.Predicates != nil { + s = append(s, "Predicates: "+fmt.Sprintf("%#v", this.Predicates)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Limit) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 7) + s = append(s, "&physicalpb.Limit{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + s = append(s, "Skip: "+fmt.Sprintf("%#v", this.Skip)+",\n") + s = append(s, "Fetch: "+fmt.Sprintf("%#v", this.Fetch)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Merge) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.Merge{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Parse) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 7) + s = append(s, "&physicalpb.Parse{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + s = append(s, "Operation: "+fmt.Sprintf("%#v", this.Operation)+",\n") + s = append(s, "RequestedKeys: "+fmt.Sprintf("%#v", this.RequestedKeys)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Projection) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 9) + s = append(s, "&physicalpb.Projection{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + if this.Expressions != nil { + s = append(s, "Expressions: "+fmt.Sprintf("%#v", this.Expressions)+",\n") + } + s = append(s, "All: "+fmt.Sprintf("%#v", this.All)+",\n") + s = append(s, "Expand: "+fmt.Sprintf("%#v", this.Expand)+",\n") + s = append(s, "Drop: "+fmt.Sprintf("%#v", this.Drop)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *SortMerge) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 7) + s = append(s, "&physicalpb.SortMerge{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + if this.Column != nil { + s = append(s, "Column: "+fmt.Sprintf("%#v", this.Column)+",\n") + } + s = append(s, "Order: "+fmt.Sprintf("%#v", this.Order)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *ColumnCompat) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 8) + s = append(s, "&physicalpb.ColumnCompat{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + s = append(s, "Source: "+fmt.Sprintf("%#v", this.Source)+",\n") + s = append(s, "Destination: "+fmt.Sprintf("%#v", this.Destination)+",\n") + s = append(s, "Collision: "+fmt.Sprintf("%#v", this.Collision)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *TopK) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 9) + s = append(s, "&physicalpb.TopK{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + if this.SortBy != nil { + s = append(s, "SortBy: "+fmt.Sprintf("%#v", this.SortBy)+",\n") + } + s = append(s, "Ascending: "+fmt.Sprintf("%#v", this.Ascending)+",\n") + s = append(s, "NullsFirst: "+fmt.Sprintf("%#v", this.NullsFirst)+",\n") + s = append(s, "K: "+fmt.Sprintf("%#v", this.K)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *ScanSet) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 8) + s = append(s, "&physicalpb.ScanSet{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + if this.Targets != nil { + s = append(s, "Targets: "+fmt.Sprintf("%#v", this.Targets)+",\n") + } + if this.Projections != nil { + s = append(s, "Projections: "+fmt.Sprintf("%#v", this.Projections)+",\n") + } + if this.Predicates != nil { + s = append(s, "Predicates: "+fmt.Sprintf("%#v", this.Predicates)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *ScanTarget) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&physicalpb.ScanTarget{") + s = append(s, "Type: "+fmt.Sprintf("%#v", this.Type)+",\n") + if this.DataObject != nil { + s = append(s, "DataObject: "+fmt.Sprintf("%#v", this.DataObject)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Parallelize) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.Parallelize{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Join) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&physicalpb.Join{") + s = append(s, "Id: "+strings.Replace(this.Id.GoString(), `&`, ``, 1)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func valueToGoStringPhysicalpb(v interface{}, typ string) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) +} +func (m *Plan) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Plan) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Plan) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Edges) > 0 { + for iNdEx := len(m.Edges) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Edges[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Nodes) > 0 { + for iNdEx := len(m.Nodes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Nodes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *PlanEdge) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PlanEdge) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PlanEdge) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Child.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.Parent.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *PlanNodeID) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PlanNodeID) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PlanNodeID) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.Value.Size() + i -= size + if _, err := m.Value.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *PlanNode) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PlanNode) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PlanNode) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Kind != nil { + { + size := m.Kind.Size() + i -= size + if _, err := m.Kind.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *PlanNode_AggregateRange) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_AggregateRange) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.AggregateRange != nil { + { + size, err := m.AggregateRange.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *PlanNode_AggregateVector) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_AggregateVector) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.AggregateVector != nil { + { + size, err := m.AggregateVector.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *PlanNode_Scan) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_Scan) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Scan != nil { + { + size, err := m.Scan.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *PlanNode_Filter) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_Filter) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Filter != nil { + { + size, err := m.Filter.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *PlanNode_Limit) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_Limit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Limit != nil { + { + size, err := m.Limit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *PlanNode_Merge) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_Merge) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Merge != nil { + { + size, err := m.Merge.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *PlanNode_Parse) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_Parse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Parse != nil { + { + size, err := m.Parse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *PlanNode_Projection) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_Projection) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Projection != nil { + { + size, err := m.Projection.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *PlanNode_SortMerge) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_SortMerge) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SortMerge != nil { + { + size, err := m.SortMerge.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + return len(dAtA) - i, nil +} +func (m *PlanNode_ColumnCompat) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_ColumnCompat) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ColumnCompat != nil { + { + size, err := m.ColumnCompat.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } + return len(dAtA) - i, nil +} +func (m *PlanNode_ScanSet) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_ScanSet) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ScanSet != nil { + { + size, err := m.ScanSet.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } + return len(dAtA) - i, nil +} +func (m *PlanNode_TopK) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_TopK) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.TopK != nil { + { + size, err := m.TopK.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + } + return len(dAtA) - i, nil +} +func (m *PlanNode_Parallelize) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_Parallelize) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Parallelize != nil { + { + size, err := m.Parallelize.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + } + return len(dAtA) - i, nil +} +func (m *PlanNode_Join) MarshalTo(dAtA []byte) (int, error) { + return m.MarshalToSizedBuffer(dAtA[:m.Size()]) +} + +func (m *PlanNode_Join) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Join != nil { + { + size, err := m.Join.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 + } + return len(dAtA) - i, nil +} +func (m *AggregateRange) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AggregateRange) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AggregateRange) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.RangeNs != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.RangeNs)) + i-- + dAtA[i] = 0x38 + } + if m.StepNs != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.StepNs)) + i-- + dAtA[i] = 0x30 + } + if m.EndUnixNanos != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.EndUnixNanos)) + i-- + dAtA[i] = 0x28 + } + if m.StartUnixNanos != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.StartUnixNanos)) + i-- + dAtA[i] = 0x20 + } + if m.Operation != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Operation)) + i-- + dAtA[i] = 0x18 + } + if len(m.PartitionBy) > 0 { + for iNdEx := len(m.PartitionBy) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PartitionBy[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *AggregateVector) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AggregateVector) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AggregateVector) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Operation != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Operation)) + i-- + dAtA[i] = 0x18 + } + if len(m.GroupBy) > 0 { + for iNdEx := len(m.GroupBy) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.GroupBy[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *DataObjScan) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DataObjScan) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DataObjScan) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Limit != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Limit)) + i-- + dAtA[i] = 0x40 + } + if m.SortOrder != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.SortOrder)) + i-- + dAtA[i] = 0x38 + } + if len(m.Predicates) > 0 { + for iNdEx := len(m.Predicates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Predicates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + } + if len(m.Projections) > 0 { + for iNdEx := len(m.Projections) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Projections[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + } + if len(m.StreamIds) > 0 { + dAtA21 := make([]byte, len(m.StreamIds)*10) + var j20 int + for _, num1 := range m.StreamIds { + num := uint64(num1) + for num >= 1<<7 { + dAtA21[j20] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j20++ + } + dAtA21[j20] = uint8(num) + j20++ + } + i -= j20 + copy(dAtA[i:], dAtA21[:j20]) + i = encodeVarintPhysicalpb(dAtA, i, uint64(j20)) + i-- + dAtA[i] = 0x22 + } + if m.Section != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Section)) + i-- + dAtA[i] = 0x18 + } + if len(m.Location) > 0 { + i -= len(m.Location) + copy(dAtA[i:], m.Location) + i = encodeVarintPhysicalpb(dAtA, i, uint64(len(m.Location))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Filter) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Filter) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Filter) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Predicates) > 0 { + for iNdEx := len(m.Predicates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Predicates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Limit) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Limit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Limit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Fetch != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Fetch)) + i-- + dAtA[i] = 0x18 + } + if m.Skip != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Skip)) + i-- + dAtA[i] = 0x10 + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Merge) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Merge) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Merge) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Parse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Parse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Parse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RequestedKeys) > 0 { + for iNdEx := len(m.RequestedKeys) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.RequestedKeys[iNdEx]) + copy(dAtA[i:], m.RequestedKeys[iNdEx]) + i = encodeVarintPhysicalpb(dAtA, i, uint64(len(m.RequestedKeys[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if m.Operation != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Operation)) + i-- + dAtA[i] = 0x10 + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Projection) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Projection) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Projection) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Drop { + i-- + if m.Drop { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if m.Expand { + i-- + if m.Expand { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + if m.All { + i-- + if m.All { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if len(m.Expressions) > 0 { + for iNdEx := len(m.Expressions) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Expressions[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *SortMerge) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SortMerge) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SortMerge) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Order != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Order)) + i-- + dAtA[i] = 0x18 + } + if m.Column != nil { + { + size, err := m.Column.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ColumnCompat) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ColumnCompat) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ColumnCompat) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Collision != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Collision)) + i-- + dAtA[i] = 0x20 + } + if m.Destination != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Destination)) + i-- + dAtA[i] = 0x18 + } + if m.Source != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Source)) + i-- + dAtA[i] = 0x10 + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *TopK) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TopK) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TopK) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.K != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.K)) + i-- + dAtA[i] = 0x28 + } + if m.NullsFirst { + i-- + if m.NullsFirst { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + if m.Ascending { + i-- + if m.Ascending { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if m.SortBy != nil { + { + size, err := m.SortBy.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ScanSet) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ScanSet) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ScanSet) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Predicates) > 0 { + for iNdEx := len(m.Predicates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Predicates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.Projections) > 0 { + for iNdEx := len(m.Projections) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Projections[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.Targets) > 0 { + for iNdEx := len(m.Targets) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Targets[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ScanTarget) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ScanTarget) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ScanTarget) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.DataObject != nil { + { + size, err := m.DataObject.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Type != 0 { + i = encodeVarintPhysicalpb(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Parallelize) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Parallelize) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Parallelize) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Join) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Join) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Join) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Id.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPhysicalpb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintPhysicalpb(dAtA []byte, offset int, v uint64) int { + offset -= sovPhysicalpb(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Plan) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Nodes) > 0 { + for _, e := range m.Nodes { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + if len(m.Edges) > 0 { + for _, e := range m.Edges { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + return n +} + +func (m *PlanEdge) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Parent.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + l = m.Child.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + return n +} + +func (m *PlanNodeID) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Value.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + return n +} + +func (m *PlanNode) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Kind != nil { + n += m.Kind.Size() + } + return n +} + +func (m *PlanNode_AggregateRange) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AggregateRange != nil { + l = m.AggregateRange.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_AggregateVector) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AggregateVector != nil { + l = m.AggregateVector.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_Scan) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Scan != nil { + l = m.Scan.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_Filter) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Filter != nil { + l = m.Filter.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_Limit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Limit != nil { + l = m.Limit.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_Merge) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Merge != nil { + l = m.Merge.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_Parse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Parse != nil { + l = m.Parse.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_Projection) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Projection != nil { + l = m.Projection.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_SortMerge) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SortMerge != nil { + l = m.SortMerge.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_ColumnCompat) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ColumnCompat != nil { + l = m.ColumnCompat.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_ScanSet) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ScanSet != nil { + l = m.ScanSet.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_TopK) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.TopK != nil { + l = m.TopK.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_Parallelize) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Parallelize != nil { + l = m.Parallelize.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *PlanNode_Join) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Join != nil { + l = m.Join.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} +func (m *AggregateRange) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + if len(m.PartitionBy) > 0 { + for _, e := range m.PartitionBy { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + if m.Operation != 0 { + n += 1 + sovPhysicalpb(uint64(m.Operation)) + } + if m.StartUnixNanos != 0 { + n += 1 + sovPhysicalpb(uint64(m.StartUnixNanos)) + } + if m.EndUnixNanos != 0 { + n += 1 + sovPhysicalpb(uint64(m.EndUnixNanos)) + } + if m.StepNs != 0 { + n += 1 + sovPhysicalpb(uint64(m.StepNs)) + } + if m.RangeNs != 0 { + n += 1 + sovPhysicalpb(uint64(m.RangeNs)) + } + return n +} + +func (m *AggregateVector) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + if len(m.GroupBy) > 0 { + for _, e := range m.GroupBy { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + if m.Operation != 0 { + n += 1 + sovPhysicalpb(uint64(m.Operation)) + } + return n +} + +func (m *DataObjScan) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + l = len(m.Location) + if l > 0 { + n += 1 + l + sovPhysicalpb(uint64(l)) + } + if m.Section != 0 { + n += 1 + sovPhysicalpb(uint64(m.Section)) + } + if len(m.StreamIds) > 0 { + l = 0 + for _, e := range m.StreamIds { + l += sovPhysicalpb(uint64(e)) + } + n += 1 + sovPhysicalpb(uint64(l)) + l + } + if len(m.Projections) > 0 { + for _, e := range m.Projections { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + if len(m.Predicates) > 0 { + for _, e := range m.Predicates { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + if m.SortOrder != 0 { + n += 1 + sovPhysicalpb(uint64(m.SortOrder)) + } + if m.Limit != 0 { + n += 1 + sovPhysicalpb(uint64(m.Limit)) + } + return n +} + +func (m *Filter) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + if len(m.Predicates) > 0 { + for _, e := range m.Predicates { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + return n +} + +func (m *Limit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + if m.Skip != 0 { + n += 1 + sovPhysicalpb(uint64(m.Skip)) + } + if m.Fetch != 0 { + n += 1 + sovPhysicalpb(uint64(m.Fetch)) + } + return n +} + +func (m *Merge) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + return n +} + +func (m *Parse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + if m.Operation != 0 { + n += 1 + sovPhysicalpb(uint64(m.Operation)) + } + if len(m.RequestedKeys) > 0 { + for _, s := range m.RequestedKeys { + l = len(s) + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + return n +} + +func (m *Projection) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + if len(m.Expressions) > 0 { + for _, e := range m.Expressions { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + if m.All { + n += 2 + } + if m.Expand { + n += 2 + } + if m.Drop { + n += 2 + } + return n +} + +func (m *SortMerge) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + if m.Column != nil { + l = m.Column.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + if m.Order != 0 { + n += 1 + sovPhysicalpb(uint64(m.Order)) + } + return n +} + +func (m *ColumnCompat) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + if m.Source != 0 { + n += 1 + sovPhysicalpb(uint64(m.Source)) + } + if m.Destination != 0 { + n += 1 + sovPhysicalpb(uint64(m.Destination)) + } + if m.Collision != 0 { + n += 1 + sovPhysicalpb(uint64(m.Collision)) + } + return n +} + +func (m *TopK) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + if m.SortBy != nil { + l = m.SortBy.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + if m.Ascending { + n += 2 + } + if m.NullsFirst { + n += 2 + } + if m.K != 0 { + n += 1 + sovPhysicalpb(uint64(m.K)) + } + return n +} + +func (m *ScanSet) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + if len(m.Targets) > 0 { + for _, e := range m.Targets { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + if len(m.Projections) > 0 { + for _, e := range m.Projections { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + if len(m.Predicates) > 0 { + for _, e := range m.Predicates { + l = e.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + } + return n +} + +func (m *ScanTarget) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + sovPhysicalpb(uint64(m.Type)) + } + if m.DataObject != nil { + l = m.DataObject.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + } + return n +} + +func (m *Parallelize) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + return n +} + +func (m *Join) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Id.Size() + n += 1 + l + sovPhysicalpb(uint64(l)) + return n +} + +func sovPhysicalpb(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozPhysicalpb(x uint64) (n int) { + return sovPhysicalpb(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *Plan) String() string { + if this == nil { + return "nil" + } + repeatedStringForNodes := "[]*PlanNode{" + for _, f := range this.Nodes { + repeatedStringForNodes += strings.Replace(f.String(), "PlanNode", "PlanNode", 1) + "," + } + repeatedStringForNodes += "}" + repeatedStringForEdges := "[]*PlanEdge{" + for _, f := range this.Edges { + repeatedStringForEdges += strings.Replace(f.String(), "PlanEdge", "PlanEdge", 1) + "," + } + repeatedStringForEdges += "}" + s := strings.Join([]string{`&Plan{`, + `Nodes:` + repeatedStringForNodes + `,`, + `Edges:` + repeatedStringForEdges + `,`, + `}`, + }, "") + return s +} +func (this *PlanEdge) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanEdge{`, + `Parent:` + strings.Replace(strings.Replace(this.Parent.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `Child:` + strings.Replace(strings.Replace(this.Child.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNodeID) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNodeID{`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode{`, + `Kind:` + fmt.Sprintf("%v", this.Kind) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_AggregateRange) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_AggregateRange{`, + `AggregateRange:` + strings.Replace(fmt.Sprintf("%v", this.AggregateRange), "AggregateRange", "AggregateRange", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_AggregateVector) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_AggregateVector{`, + `AggregateVector:` + strings.Replace(fmt.Sprintf("%v", this.AggregateVector), "AggregateVector", "AggregateVector", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_Scan) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_Scan{`, + `Scan:` + strings.Replace(fmt.Sprintf("%v", this.Scan), "DataObjScan", "DataObjScan", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_Filter) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_Filter{`, + `Filter:` + strings.Replace(fmt.Sprintf("%v", this.Filter), "Filter", "Filter", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_Limit) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_Limit{`, + `Limit:` + strings.Replace(fmt.Sprintf("%v", this.Limit), "Limit", "Limit", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_Merge) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_Merge{`, + `Merge:` + strings.Replace(fmt.Sprintf("%v", this.Merge), "Merge", "Merge", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_Parse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_Parse{`, + `Parse:` + strings.Replace(fmt.Sprintf("%v", this.Parse), "Parse", "Parse", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_Projection) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_Projection{`, + `Projection:` + strings.Replace(fmt.Sprintf("%v", this.Projection), "Projection", "Projection", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_SortMerge) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_SortMerge{`, + `SortMerge:` + strings.Replace(fmt.Sprintf("%v", this.SortMerge), "SortMerge", "SortMerge", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_ColumnCompat) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_ColumnCompat{`, + `ColumnCompat:` + strings.Replace(fmt.Sprintf("%v", this.ColumnCompat), "ColumnCompat", "ColumnCompat", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_ScanSet) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_ScanSet{`, + `ScanSet:` + strings.Replace(fmt.Sprintf("%v", this.ScanSet), "ScanSet", "ScanSet", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_TopK) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_TopK{`, + `TopK:` + strings.Replace(fmt.Sprintf("%v", this.TopK), "TopK", "TopK", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_Parallelize) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_Parallelize{`, + `Parallelize:` + strings.Replace(fmt.Sprintf("%v", this.Parallelize), "Parallelize", "Parallelize", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PlanNode_Join) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PlanNode_Join{`, + `Join:` + strings.Replace(fmt.Sprintf("%v", this.Join), "Join", "Join", 1) + `,`, + `}`, + }, "") + return s +} +func (this *AggregateRange) String() string { + if this == nil { + return "nil" + } + repeatedStringForPartitionBy := "[]*ColumnExpression{" + for _, f := range this.PartitionBy { + repeatedStringForPartitionBy += strings.Replace(fmt.Sprintf("%v", f), "ColumnExpression", "ColumnExpression", 1) + "," + } + repeatedStringForPartitionBy += "}" + s := strings.Join([]string{`&AggregateRange{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `PartitionBy:` + repeatedStringForPartitionBy + `,`, + `Operation:` + fmt.Sprintf("%v", this.Operation) + `,`, + `StartUnixNanos:` + fmt.Sprintf("%v", this.StartUnixNanos) + `,`, + `EndUnixNanos:` + fmt.Sprintf("%v", this.EndUnixNanos) + `,`, + `StepNs:` + fmt.Sprintf("%v", this.StepNs) + `,`, + `RangeNs:` + fmt.Sprintf("%v", this.RangeNs) + `,`, + `}`, + }, "") + return s +} +func (this *AggregateVector) String() string { + if this == nil { + return "nil" + } + repeatedStringForGroupBy := "[]*ColumnExpression{" + for _, f := range this.GroupBy { + repeatedStringForGroupBy += strings.Replace(fmt.Sprintf("%v", f), "ColumnExpression", "ColumnExpression", 1) + "," + } + repeatedStringForGroupBy += "}" + s := strings.Join([]string{`&AggregateVector{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `GroupBy:` + repeatedStringForGroupBy + `,`, + `Operation:` + fmt.Sprintf("%v", this.Operation) + `,`, + `}`, + }, "") + return s +} +func (this *DataObjScan) String() string { + if this == nil { + return "nil" + } + repeatedStringForProjections := "[]*ColumnExpression{" + for _, f := range this.Projections { + repeatedStringForProjections += strings.Replace(fmt.Sprintf("%v", f), "ColumnExpression", "ColumnExpression", 1) + "," + } + repeatedStringForProjections += "}" + repeatedStringForPredicates := "[]*Expression{" + for _, f := range this.Predicates { + repeatedStringForPredicates += strings.Replace(fmt.Sprintf("%v", f), "Expression", "Expression", 1) + "," + } + repeatedStringForPredicates += "}" + s := strings.Join([]string{`&DataObjScan{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `Location:` + fmt.Sprintf("%v", this.Location) + `,`, + `Section:` + fmt.Sprintf("%v", this.Section) + `,`, + `StreamIds:` + fmt.Sprintf("%v", this.StreamIds) + `,`, + `Projections:` + repeatedStringForProjections + `,`, + `Predicates:` + repeatedStringForPredicates + `,`, + `SortOrder:` + fmt.Sprintf("%v", this.SortOrder) + `,`, + `Limit:` + fmt.Sprintf("%v", this.Limit) + `,`, + `}`, + }, "") + return s +} +func (this *Filter) String() string { + if this == nil { + return "nil" + } + repeatedStringForPredicates := "[]*Expression{" + for _, f := range this.Predicates { + repeatedStringForPredicates += strings.Replace(fmt.Sprintf("%v", f), "Expression", "Expression", 1) + "," + } + repeatedStringForPredicates += "}" + s := strings.Join([]string{`&Filter{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `Predicates:` + repeatedStringForPredicates + `,`, + `}`, + }, "") + return s +} +func (this *Limit) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Limit{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `Skip:` + fmt.Sprintf("%v", this.Skip) + `,`, + `Fetch:` + fmt.Sprintf("%v", this.Fetch) + `,`, + `}`, + }, "") + return s +} +func (this *Merge) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Merge{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *Parse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Parse{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `Operation:` + fmt.Sprintf("%v", this.Operation) + `,`, + `RequestedKeys:` + fmt.Sprintf("%v", this.RequestedKeys) + `,`, + `}`, + }, "") + return s +} +func (this *Projection) String() string { + if this == nil { + return "nil" + } + repeatedStringForExpressions := "[]*Expression{" + for _, f := range this.Expressions { + repeatedStringForExpressions += strings.Replace(fmt.Sprintf("%v", f), "Expression", "Expression", 1) + "," + } + repeatedStringForExpressions += "}" + s := strings.Join([]string{`&Projection{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `Expressions:` + repeatedStringForExpressions + `,`, + `All:` + fmt.Sprintf("%v", this.All) + `,`, + `Expand:` + fmt.Sprintf("%v", this.Expand) + `,`, + `Drop:` + fmt.Sprintf("%v", this.Drop) + `,`, + `}`, + }, "") + return s +} +func (this *SortMerge) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&SortMerge{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `Column:` + strings.Replace(fmt.Sprintf("%v", this.Column), "ColumnExpression", "ColumnExpression", 1) + `,`, + `Order:` + fmt.Sprintf("%v", this.Order) + `,`, + `}`, + }, "") + return s +} +func (this *ColumnCompat) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ColumnCompat{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `Source:` + fmt.Sprintf("%v", this.Source) + `,`, + `Destination:` + fmt.Sprintf("%v", this.Destination) + `,`, + `Collision:` + fmt.Sprintf("%v", this.Collision) + `,`, + `}`, + }, "") + return s +} +func (this *TopK) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&TopK{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `SortBy:` + strings.Replace(fmt.Sprintf("%v", this.SortBy), "ColumnExpression", "ColumnExpression", 1) + `,`, + `Ascending:` + fmt.Sprintf("%v", this.Ascending) + `,`, + `NullsFirst:` + fmt.Sprintf("%v", this.NullsFirst) + `,`, + `K:` + fmt.Sprintf("%v", this.K) + `,`, + `}`, + }, "") + return s +} +func (this *ScanSet) String() string { + if this == nil { + return "nil" + } + repeatedStringForTargets := "[]*ScanTarget{" + for _, f := range this.Targets { + repeatedStringForTargets += strings.Replace(f.String(), "ScanTarget", "ScanTarget", 1) + "," + } + repeatedStringForTargets += "}" + repeatedStringForProjections := "[]*ColumnExpression{" + for _, f := range this.Projections { + repeatedStringForProjections += strings.Replace(fmt.Sprintf("%v", f), "ColumnExpression", "ColumnExpression", 1) + "," + } + repeatedStringForProjections += "}" + repeatedStringForPredicates := "[]*Expression{" + for _, f := range this.Predicates { + repeatedStringForPredicates += strings.Replace(fmt.Sprintf("%v", f), "Expression", "Expression", 1) + "," + } + repeatedStringForPredicates += "}" + s := strings.Join([]string{`&ScanSet{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `Targets:` + repeatedStringForTargets + `,`, + `Projections:` + repeatedStringForProjections + `,`, + `Predicates:` + repeatedStringForPredicates + `,`, + `}`, + }, "") + return s +} +func (this *ScanTarget) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ScanTarget{`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `DataObject:` + strings.Replace(this.DataObject.String(), "DataObjScan", "DataObjScan", 1) + `,`, + `}`, + }, "") + return s +} +func (this *Parallelize) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Parallelize{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *Join) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Join{`, + `Id:` + strings.Replace(strings.Replace(this.Id.String(), "PlanNodeID", "PlanNodeID", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func valueToStringPhysicalpb(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *Plan) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Plan: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Plan: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Nodes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Nodes = append(m.Nodes, &PlanNode{}) + if err := m.Nodes[len(m.Nodes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Edges", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Edges = append(m.Edges, &PlanEdge{}) + if err := m.Edges[len(m.Edges)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PlanEdge) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PlanEdge: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PlanEdge: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Parent", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Parent.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Child", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Child.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PlanNodeID) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PlanNodeID: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PlanNodeID: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Value.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PlanNode) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PlanNode: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PlanNode: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggregateRange", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &AggregateRange{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_AggregateRange{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggregateVector", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &AggregateVector{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_AggregateVector{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Scan", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &DataObjScan{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_Scan{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Filter", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Filter{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_Filter{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Limit{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_Limit{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Merge", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Merge{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_Merge{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Parse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Parse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_Parse{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Projection", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Projection{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_Projection{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SortMerge", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SortMerge{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_SortMerge{v} + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ColumnCompat", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ColumnCompat{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_ColumnCompat{v} + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ScanSet", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ScanSet{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_ScanSet{v} + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TopK", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &TopK{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_TopK{v} + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Parallelize", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Parallelize{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_Parallelize{v} + iNdEx = postIndex + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Join", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Join{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Kind = &PlanNode_Join{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AggregateRange) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AggregateRange: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AggregateRange: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PartitionBy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PartitionBy = append(m.PartitionBy, &ColumnExpression{}) + if err := m.PartitionBy[len(m.PartitionBy)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Operation", wireType) + } + m.Operation = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Operation |= AggregateRangeOp(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field StartUnixNanos", wireType) + } + m.StartUnixNanos = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.StartUnixNanos |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EndUnixNanos", wireType) + } + m.EndUnixNanos = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.EndUnixNanos |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field StepNs", wireType) + } + m.StepNs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.StepNs |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RangeNs", wireType) + } + m.RangeNs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RangeNs |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AggregateVector) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AggregateVector: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AggregateVector: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupBy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GroupBy = append(m.GroupBy, &ColumnExpression{}) + if err := m.GroupBy[len(m.GroupBy)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Operation", wireType) + } + m.Operation = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Operation |= AggregateVectorOp(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DataObjScan) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DataObjScan: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DataObjScan: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Location", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Location = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Section", wireType) + } + m.Section = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Section |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType == 0 { + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.StreamIds = append(m.StreamIds, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.StreamIds) == 0 { + m.StreamIds = make([]int64, 0, elementCount) + } + for iNdEx < postIndex { + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.StreamIds = append(m.StreamIds, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field StreamIds", wireType) + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Projections", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Projections = append(m.Projections, &ColumnExpression{}) + if err := m.Projections[len(m.Projections)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Predicates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Predicates = append(m.Predicates, &Expression{}) + if err := m.Predicates[len(m.Predicates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SortOrder", wireType) + } + m.SortOrder = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SortOrder |= SortOrder(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + m.Limit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Limit |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Filter) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Filter: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Filter: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Predicates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Predicates = append(m.Predicates, &Expression{}) + if err := m.Predicates[len(m.Predicates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Limit) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Limit: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Limit: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Skip", wireType) + } + m.Skip = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Skip |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Fetch", wireType) + } + m.Fetch = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Fetch |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Merge) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Merge: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Merge: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Parse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Parse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Parse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Operation", wireType) + } + m.Operation = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Operation |= ParseOp(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RequestedKeys", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RequestedKeys = append(m.RequestedKeys, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Projection) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Projection: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Projection: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expressions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Expressions = append(m.Expressions, &Expression{}) + if err := m.Expressions[len(m.Expressions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field All", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.All = bool(v != 0) + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Expand", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Expand = bool(v != 0) + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Drop", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Drop = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SortMerge) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SortMerge: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SortMerge: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Column", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Column == nil { + m.Column = &ColumnExpression{} + } + if err := m.Column.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Order", wireType) + } + m.Order = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Order |= SortOrder(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ColumnCompat) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ColumnCompat: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ColumnCompat: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Source", wireType) + } + m.Source = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Source |= ColumnType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Destination", wireType) + } + m.Destination = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Destination |= ColumnType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Collision", wireType) + } + m.Collision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Collision |= ColumnType(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TopK) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TopK: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TopK: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SortBy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SortBy == nil { + m.SortBy = &ColumnExpression{} + } + if err := m.SortBy.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Ascending", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Ascending = bool(v != 0) + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NullsFirst", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.NullsFirst = bool(v != 0) + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field K", wireType) + } + m.K = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.K |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ScanSet) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ScanSet: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ScanSet: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Targets", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Targets = append(m.Targets, &ScanTarget{}) + if err := m.Targets[len(m.Targets)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Projections", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Projections = append(m.Projections, &ColumnExpression{}) + if err := m.Projections[len(m.Projections)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Predicates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Predicates = append(m.Predicates, &Expression{}) + if err := m.Predicates[len(m.Predicates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ScanTarget) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ScanTarget: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ScanTarget: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= ScanType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DataObject", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DataObject == nil { + m.DataObject = &DataObjScan{} + } + if err := m.DataObject.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Parallelize) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Parallelize: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Parallelize: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Join) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Join: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Join: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPhysicalpb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPhysicalpb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPhysicalpb(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPhysicalpb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipPhysicalpb(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthPhysicalpb + } + iNdEx += length + if iNdEx < 0 { + return 0, ErrInvalidLengthPhysicalpb + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPhysicalpb + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipPhysicalpb(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + if iNdEx < 0 { + return 0, ErrInvalidLengthPhysicalpb + } + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthPhysicalpb = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowPhysicalpb = fmt.Errorf("proto: integer overflow") +) diff --git a/pkg/engine/internal/planner/physical/physicalpb/physicalpb.proto b/pkg/engine/internal/planner/physical/physicalpb/physicalpb.proto new file mode 100644 index 0000000000000..6cb4c6aabeebe --- /dev/null +++ b/pkg/engine/internal/planner/physical/physicalpb/physicalpb.proto @@ -0,0 +1,289 @@ +// physicalpb.proto holds types for a query engine's physical plan. +syntax = "proto3"; + +package physical.engine.loki.v1; + +import "gogoproto/gogo.proto"; +import public "pkg/engine/internal/planner/physical/physicalpb/expression.proto"; +import "pkg/engine/internal/util/ulid/ulid.proto"; + +option go_package = "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb"; + +// Plan represents the physical plan of a query. +message Plan { + repeated PlanNode nodes = 1; + repeated PlanEdge edges = 2; +} + +enum WalkOrder { + PRE_ORDER_WALK = 0; // PreOrderWalk processes the current vertex before visiting any of its children. + POST_ORDER_WALK = 1; // PostOrderWalk processes the current vertex after visiting all of its children. +} + +// PlanEdge represents a relationship between two nodes in the physical plan. +message PlanEdge { + PlanNodeID parent = 1 [(gogoproto.nullable) = false]; + PlanNodeID child = 2 [(gogoproto.nullable) = false]; +} + +message PlanNodeID { + ulid.loki.v1.ProtoULID value = 1 [ + (gogoproto.customtype) = "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid.ULID", + (gogoproto.nullable) = false + ]; +} + +// PlanNode represents a node in the physical plan. +message PlanNode { + oneof kind { + AggregateRange aggregate_range = 1; + AggregateVector aggregate_vector = 2; + DataObjScan scan = 3; + Filter filter = 4; + Limit limit = 5; + Merge merge = 6; + Parse parse = 7; + Projection projection = 8; + SortMerge sort_merge = 9; + ColumnCompat column_compat = 10; + ScanSet scan_set = 11; + TopK top_k = 12; + Parallelize parallelize = 13; + Join join = 14; + } +} + +// AggregateRange aggregates samples into windowed ranges. +message AggregateRange { + // ID for the node. + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + + // Columns to partition the data by. + repeated ColumnExpression partition_by = 2; + + AggregateRangeOp operation = 3; + + int64 start_unix_nanos = 4; + int64 end_unix_nanos = 5; + int64 step_ns = 6; + int64 range_ns = 7; +} + +// AggregateRangeOp represents the operation to perform on the aggregated +// data. +enum AggregateRangeOp { + AGGREGATE_RANGE_OP_INVALID = 0; // Invalid range aggregation operation. + + AGGREGATE_RANGE_OP_COUNT = 1; // Represents LogQL's count_over_time aggregation. + AGGREGATE_RANGE_OP_SUM = 2; // Represents LogQL's sum_over_time aggregation. + AGGREGATE_RANGE_OP_MAX = 3; // Represents LogQL's max_over_time aggregation. + AGGREGATE_RANGE_OP_MIN = 4; // Represents LogQL's min_over_time aggregation. +} + +// AggregateVector represents an operation to aggregate a range vector into an +// instant vector, with optional grouping on specified dimensions. +message AggregateVector { + // ID for the node. + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + + // Columns to group the data by. If empty, all rows are aggregated into a single result. + repeated ColumnExpression group_by = 2; + + // Aggregation operation to perform over the underlying range vector. + AggregateVectorOp operation = 3; +} + +// AggregateVectorOp represents the different aggregation operations that can +// be performed on a range vector. +enum AggregateVectorOp { + AGGREGATE_VECTOR_OP_INVALID = 0; // Invalid vector aggregation operation. + + AGGREGATE_VECTOR_OP_SUM = 1; // Represents LogQL's sum vector aggregation. + AGGREGATE_VECTOR_OP_MAX = 2; // Represents LogQL's max vector aggregation. + AGGREGATE_VECTOR_OP_MIN = 3; // Represents LogQL's min vector aggregation. + AGGREGATE_VECTOR_OP_COUNT = 4; // Represents LogQL's count vector aggregation. + AGGREGATE_VECTOR_OP_AVG = 5; // Represents LogQL's avg vector aggregation. + AGGREGATE_VECTOR_OP_STDDEV = 6; // Represents LogQL's stddev vector aggregation. + AGGREGATE_VECTOR_OP_STDVAR = 7; // Represents LogQL's stdvar vector aggregation. + AGGREGATE_VECTOR_OP_BOTTOMK = 8; // Represents LogQL's bottomk vector aggregation. + AGGREGATE_VECTOR_OP_TOPK = 9; // Represents LogQL's topk vector aggregation. + AGGREGATE_VECTOR_OP_SORT = 10; // Represents LogQL's sort vector aggregation. + AGGREGATE_VECTOR_OP_SORT_DESC = 11; // Represents LogQL's sort_desc vector aggregation. +} + +// DataObjScan represents an operation to read the contents of a data object +// section. +message DataObjScan { + // ID for the node. + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + + // Stored location of the data object to read. + string location = 2; + + // Section within the data object to read. + int64 section = 3; + + // StreamIDs within the section to read. + repeated int64 stream_ids = 4; + + // Projections are used to limit the columns that are read. + repeated ColumnExpression projections = 5; + + // Predicates are used to filter rows to reduce the amount of rows that are + // returned. + repeated Expression predicates = 6; + + // Sort order for the scan. + SortOrder sort_order = 7; + + // Limit of rows to return. + uint32 limit = 8; +} + +// Filter represents an operation to filter rows based on a condition. +message Filter { + // ID for the node. + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + + // Predicates to apply to filter rows. + repeated Expression predicates = 2; +} + +// Limit represents a limiting operation in the physical plan that applies +// offset and limit to the result set. +message Limit { + // ID for the node. + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + + // Skip specifies how many initial rows should be skipped. + uint32 skip = 2; + + // Fetch specifies how many rows should be returned in total. + uint32 fetch = 3; +} + +// Merge represents an operation in the physical plan that merges a sequence of +// inputs into a single output, retaining the order of the inputs. +message Merge { + // ID for the node. + PlanNodeID id = 1 [(gogoproto.nullable) = false]; +} + +// Parse represents an operation to parse a log message into multiple key-value +// pairs. +message Parse { + // ID for the node. + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + + ParseOp operation = 2; + repeated string requested_keys = 3; +} + +// ParseOp represents the type of parse operation to be performed. +enum ParseOp { + PARSE_OP_INVALID = 0; // Invalid parse operation. + + PARSE_OP_LOGFMT = 1; // Logfmt parse operation. + PARSE_OP_JSON = 2; // JSON parse operation. +} + +// Projection represents an operation to return a subset of columns from the +// input. +message Projection { + // ID for the node. + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + // Expressions is a set of column expressions that are used to drop not needed + // columns that match the column expression, or to expand columns that result + // from the expressions. + repeated Expression Expressions = 2; + bool All = 3; // Marker for projecting all columns of input relation (similar to SQL `SELECT *`) + bool Expand = 4; // Indicates that projected columns should be added to input relation + bool Drop = 5; // Indicates that projected columns should be dropped from input Relation + +// Columns that should be kept in the output. +} + +// SortMerge represents an operation in the physical plan. It merges a sequence +// of sorted inputs into a single sorted output. +message SortMerge { + // ID for the node. + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + + // Column defines the column by which the rows should be sorted. This is almost always + // the timestamp column, as it is the column by which DataObjScan results + // are sorted. + ColumnExpression column = 2; + + // Order defines how rows for the column are sorted. Must match the sort + // order of the inputs. + SortOrder order = 3; +} + +// SortOrder represents the order in which results should be sorted. +enum SortOrder { + SORT_ORDER_INVALID = 0; // Invalid sort order. + SORT_ORDER_ASCENDING = 1; // Ascending sort order. + SORT_ORDER_DESCENDING = 2; // Descending sort order. +} + +// ColumnCompat represents a compactibilty operation in the physical plan that +// moves a values from a conflicting metadata column with a label column into a new column suffixed with `_extracted`. +message ColumnCompat { + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + + // TODO(chaudum): These fields are poorly named. Come up with more descriptive names. + ColumnType Source = 2; // column type of the column that may colide with columns of the same name but with collision type + ColumnType Destination = 3; // column type of the generated _extracted column (should be same as source) + ColumnType Collision = 4; // column type of the column that a source type column may collide with} +} + +message TopK { + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + ColumnExpression SortBy = 2; // SortBy is the column to sort by. + bool Ascending = 3; // Sort lines in ascending order if true. + bool NullsFirst = 4; // When true, considers NULLs < non-NULLs when sorting. + int64 K = 5; // Number of top rows to return. +} + +// ScanSet represents a physical plan operation for reading data from targets. +message ScanSet { + PlanNodeID id = 1 [(gogoproto.nullable) = false]; + // Targets to scan + repeated ScanTarget Targets = 2; + // Projections are used to limit the columns that are read to the ones + // provided in the column expressions to reduce the amount of data that + // needs to be processed. + repeated ColumnExpression Projections = 3; + // Predicates are used to filter rows to reduce the amount of rows that are + // returned. Predicates would almost always contain a time range filter to + // only read the logs for the requested time range. + repeated Expression Predicates = 4; +} + +// ScanTarget represents a target of a [ScanSet]. +message ScanTarget { + ScanType Type = 1; + + // DataObject is non-nil if Type is [ScanTypeDataObject]. Despite DataObjScan + // implementing [Node], the value is not inserted into the graph as a node. + DataObjScan DataObject = 2; +} + +// ScanType represents the data being scanned in a target of a [ScanSet]. +enum ScanType { + SCAN_TYPE_INVALID = 0; + SCAN_TYPE_DATA_OBJECT = 1; +} + +// Parallelize represents a hint to the engine to partition and parallelize the +// children branches of the Parallelize and emit results as a single sequence +// with no guaranteed order. +message Parallelize { + PlanNodeID id = 1 [(gogoproto.nullable) = false]; +} + +// Join represents a join operation in the physical plan. +// For now it is only an inner join on `timestamp`. Will be expanded later. +message Join { + PlanNodeID id = 1 [(gogoproto.nullable) = false]; +} diff --git a/pkg/engine/internal/planner/physical/physicalpb/plan_test.go b/pkg/engine/internal/planner/physical/physicalpb/plan_test.go new file mode 100644 index 0000000000000..d5f098713ca1f --- /dev/null +++ b/pkg/engine/internal/planner/physical/physicalpb/plan_test.go @@ -0,0 +1,221 @@ +package physicalpb_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" + "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" + "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid" +) + +func TestGraph(t *testing.T) { + t.Run("empty graph does not have roots and leaves", func(t *testing.T) { + var p physicalpb.Plan + + require.Len(t, p.Roots(), 0) + require.Len(t, p.Leaves(), 0) + }) + + t.Run("adding a single node makes it both root and leave node", func(t *testing.T) { + var p physicalpb.Plan + scanID := physicalpb.PlanNodeID{Value: ulid.New()} + p.Add(&physicalpb.DataObjScan{Id: scanID}) + + require.Len(t, p.Roots(), 1) + require.Len(t, p.Leaves(), 1) + }) + + t.Run("adding an edge for nodes that do not exist fails", func(t *testing.T) { + var p physicalpb.Plan + scanID := physicalpb.PlanNodeID{Value: ulid.New()} + sortID := physicalpb.PlanNodeID{Value: ulid.New()} + + err := p.AddEdge(dag.Edge[physicalpb.Node]{ + Parent: &physicalpb.SortMerge{Id: sortID}, + Child: &physicalpb.DataObjScan{Id: scanID}, + }) + require.ErrorContains(t, err, fmt.Sprintf("both nodes %v and %v must already exist in the plan", sortID.Value.String(), scanID.Value.String())) + }) + + t.Run("adding an edge for zero value nodes fails", func(t *testing.T) { + var p physicalpb.Plan + + err := p.AddEdge(dag.Edge[physicalpb.Node]{Parent: nil, Child: nil}) + require.ErrorContains(t, err, "parent and child nodes must not be zero values") + }) + + t.Run("test roots and leaves", func(t *testing.T) { + var p physicalpb.Plan + scan1ID := physicalpb.PlanNodeID{Value: ulid.New()} + scan2ID := physicalpb.PlanNodeID{Value: ulid.New()} + mergeID := physicalpb.PlanNodeID{Value: ulid.New()} + + var ( + scan1 = p.Add(&physicalpb.DataObjScan{Id: scan1ID}) + scan2 = p.Add(&physicalpb.DataObjScan{Id: scan2ID}) + merge = p.Add(&physicalpb.Merge{Id: mergeID}) + ) + + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(merge), Child: physicalpb.GetNode(scan1)}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(merge), Child: physicalpb.GetNode(scan2)}) + + require.Equal(t, len(p.Nodes), 3) + require.Len(t, p.Roots(), 1) + require.Equal(t, mergeID.Value.String(), p.Roots()[0].ID()) + require.Len(t, p.Leaves(), 2) + }) + + t.Run("child ordering is preserved", func(t *testing.T) { + var p physicalpb.Plan + parentID := physicalpb.PlanNodeID{Value: ulid.New()} + child1ID := physicalpb.PlanNodeID{Value: ulid.New()} + child2ID := physicalpb.PlanNodeID{Value: ulid.New()} + var ( + parent = p.Add(&physicalpb.Merge{Id: parentID}) + child1 = p.Add(&physicalpb.Merge{Id: child1ID}) + child2 = p.Add(&physicalpb.Merge{Id: child2ID}) + ) + + require.NoError(t, p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parent), Child: physicalpb.GetNode(child1)})) + require.NoError(t, p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parent), Child: physicalpb.GetNode(child2)})) + require.Equal(t, []physicalpb.Node{child1.GetMerge(), child2.GetMerge()}, p.Children(physicalpb.GetNode(parent))) + }) + + t.Run("test eliminate node", func(t *testing.T) { + var p physicalpb.Plan + parentID := physicalpb.PlanNodeID{Value: ulid.New()} + middleID := physicalpb.PlanNodeID{Value: ulid.New()} + child1ID := physicalpb.PlanNodeID{Value: ulid.New()} + child2ID := physicalpb.PlanNodeID{Value: ulid.New()} + + var ( + parent = p.Add(&physicalpb.Merge{Id: parentID}) + middle = p.Add(&physicalpb.Merge{Id: middleID}) + child1 = p.Add(&physicalpb.Merge{Id: child1ID}) + child2 = p.Add(&physicalpb.Merge{Id: child2ID}) + ) + + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parent), Child: physicalpb.GetNode(middle)}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(middle), Child: physicalpb.GetNode(child1)}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(middle), Child: physicalpb.GetNode(child2)}) + + require.Equal(t, len(p.Nodes), 4) + require.Equal(t, []physicalpb.Node{physicalpb.GetNode(parent)}, p.Parents(physicalpb.GetNode(middle))) + require.Equal(t, []physicalpb.Node{physicalpb.GetNode(middle)}, p.Parents(physicalpb.GetNode(child1))) + require.Equal(t, []physicalpb.Node{physicalpb.GetNode(middle)}, p.Parents(physicalpb.GetNode(child2))) + + p.Eliminate(physicalpb.GetNode(middle)) + + require.Equal(t, len(p.Nodes), 3) + require.Equal(t, []physicalpb.Node{physicalpb.GetNode(parent)}, p.Parents(physicalpb.GetNode(child1))) + require.Equal(t, []physicalpb.Node{physicalpb.GetNode(parent)}, p.Parents(physicalpb.GetNode(child2))) + require.Equal(t, []physicalpb.Node{physicalpb.GetNode(child1), physicalpb.GetNode(child2)}, p.Children(physicalpb.GetNode(parent))) + }) + t.Run("test root returns error for empty graph", func(t *testing.T) { + var p physicalpb.Plan + + _, err := p.Root() + require.ErrorContains(t, err, "plan has no root node") + }) + + t.Run("test root returns error for multiple roots", func(t *testing.T) { + root1ID := physicalpb.PlanNodeID{Value: ulid.New()} + root2ID := physicalpb.PlanNodeID{Value: ulid.New()} + var p physicalpb.Plan + p.Add(&physicalpb.Merge{Id: root1ID}) + p.Add(&physicalpb.Merge{Id: root2ID}) + + _, err := p.Root() + require.ErrorContains(t, err, "plan has multiple root nodes") + }) + + t.Run("test root returns single root", func(t *testing.T) { + rootID := physicalpb.PlanNodeID{Value: ulid.New()} + childID := physicalpb.PlanNodeID{Value: ulid.New()} + var p physicalpb.Plan + + var ( + root = p.Add(&physicalpb.Merge{Id: rootID}) + child = p.Add(&physicalpb.Merge{Id: childID}) + ) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(root), Child: physicalpb.GetNode(child)}) + + actualRoot, err := p.Root() + require.NoError(t, err) + require.Equal(t, physicalpb.GetNode(root).ID(), actualRoot.ID()) + }) + + t.Run("adding zero value node is no-op", func(t *testing.T) { + var p physicalpb.Plan + + p.Add(nil) + require.Equal(t, 0, len(p.Nodes)) + }) + + t.Run("parent and children methods handle missing nodes", func(t *testing.T) { + var p physicalpb.Plan + nonExistentID := physicalpb.PlanNodeID{Value: ulid.New()} + nonExistent := &physicalpb.Merge{Id: nonExistentID} + + require.Empty(t, p.Parents(nonExistent)) + require.Empty(t, p.Children(nonExistent)) + }) + + t.Run("walk with error stops traversal", func(t *testing.T) { + rootID := physicalpb.PlanNodeID{Value: ulid.New()} + childID := physicalpb.PlanNodeID{Value: ulid.New()} + var p physicalpb.Plan + + var ( + root = p.Add(&physicalpb.Merge{Id: rootID}) + child = p.Add(&physicalpb.Merge{Id: childID}) + ) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(root), Child: physicalpb.GetNode(child)}) + + expectedErr := fmt.Errorf("test error") + err := p.Walk(physicalpb.GetNode(root), func(physicalpb.Node) error { return expectedErr }, physicalpb.PRE_ORDER_WALK) + require.Equal(t, expectedErr, err) + }) + + t.Run("test inject node", func(t *testing.T) { + var p physicalpb.Plan + parentID := physicalpb.PlanNodeID{Value: ulid.New()} + child1ID := physicalpb.PlanNodeID{Value: ulid.New()} + child2ID := physicalpb.PlanNodeID{Value: ulid.New()} + injectedID := physicalpb.PlanNodeID{Value: ulid.New()} + var ( + parent = p.Add(&physicalpb.Merge{Id: parentID}) + child1 = p.Add(&physicalpb.Merge{Id: child1ID}) + child2 = p.Add(&physicalpb.Merge{Id: child2ID}) + ) + + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parent), Child: physicalpb.GetNode(child1)}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parent), Child: physicalpb.GetNode(child2)}) + + newNode := p.Inject(physicalpb.GetNode(parent), &physicalpb.Merge{Id: injectedID}) + + require.Equal(t, len(p.Nodes), 4) + require.Equal(t, []physicalpb.Node{physicalpb.GetNode(parent)}, p.Parents(newNode)) + require.Equal(t, []physicalpb.Node{newNode}, p.Parents(physicalpb.GetNode(child1))) + require.Equal(t, []physicalpb.Node{newNode}, p.Parents(physicalpb.GetNode(child2))) + require.Equal(t, []physicalpb.Node{newNode}, p.Children(physicalpb.GetNode(parent))) + require.Equal(t, []physicalpb.Node{physicalpb.GetNode(child1), physicalpb.GetNode(child2)}, p.Children(newNode)) + }) + + t.Run("test inject node panics if node already exists", func(t *testing.T) { + var p physicalpb.Plan + parentID := physicalpb.PlanNodeID{Value: ulid.New()} + existingID := physicalpb.PlanNodeID{Value: ulid.New()} + + var ( + parent = p.Add(&physicalpb.Merge{Id: parentID}) + existing = p.Add(&physicalpb.Merge{Id: existingID}) + ) + + require.Panics(t, func() { p.Inject(physicalpb.GetNode(parent), physicalpb.GetNode(existing)) }) + }) + +} diff --git a/pkg/engine/internal/planner/physical/plan.go b/pkg/engine/internal/planner/physical/plan.go deleted file mode 100644 index 21067922aca34..0000000000000 --- a/pkg/engine/internal/planner/physical/plan.go +++ /dev/null @@ -1,183 +0,0 @@ -package physical - -import ( - "iter" - - "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" -) - -type NodeType uint32 - -const ( - NodeTypeDataObjScan NodeType = iota - NodeTypeSortMerge - NodeTypeProjection - NodeTypeFilter - NodeTypeLimit - NodeTypeRangeAggregation - NodeTypeVectorAggregation - NodeTypeMerge - NodeTypeParse - NodeTypeCompat - NodeTypeTopK - NodeTypeParallelize - NodeTypeScanSet - NodeTypeJoin -) - -func (t NodeType) String() string { - switch t { - case NodeTypeDataObjScan: - return "DataObjScan" - case NodeTypeSortMerge: - return "SortMerge" - case NodeTypeMerge: - return "Merge" - case NodeTypeProjection: - return "Projection" - case NodeTypeFilter: - return "Filter" - case NodeTypeLimit: - return "Limit" - case NodeTypeRangeAggregation: - return "RangeAggregation" - case NodeTypeVectorAggregation: - return "VectorAggregation" - case NodeTypeParse: - return "Parse" - case NodeTypeCompat: - return "Compat" - case NodeTypeTopK: - return "TopK" - case NodeTypeParallelize: - return "Parallelize" - case NodeTypeScanSet: - return "ScanSet" - case NodeTypeJoin: - return "Join" - default: - return "Undefined" - } -} - -// Node represents a single operation in a physical execution plan. -// It defines the core interface that all physical plan nodes must implement. -// Each node represents a specific operation like scanning, filtering, or -// transforming data. -// Nodes can be connected to form a directed acyclic graph (DAG) representing -// the complete execution plan. -type Node interface { - // ID returns a string that uniquely identifies a node in the plan - ID() string - // Type returns the node type - Type() NodeType - // Clone creates a deep copy of the Node. Cloned nodes do not retain the - // same ID. - Clone() Node - // Accept allows the object to be visited by a [Visitor] as part of the - // visitor pattern. It typically calls back to the appropriate Visit method - // on the Visitor for the concrete type being visited. - Accept(Visitor) error - // isNode is a marker interface to denote a node, and only allows it to be - // implemented within this package - isNode() -} - -// ShardableNode is a Node that can be split into multiple smaller partitions. -type ShardableNode interface { - Node - - // Shards produces a sequence of nodes that represent a fragment of the - // original node. Returned nodes do not need to be the same type as the - // original node. - // - // Implementations must produce unique values of Node in each call to - // Shards. - Shards() iter.Seq[Node] -} - -var _ Node = (*DataObjScan)(nil) -var _ Node = (*Projection)(nil) -var _ Node = (*Limit)(nil) -var _ Node = (*Filter)(nil) -var _ Node = (*RangeAggregation)(nil) -var _ Node = (*VectorAggregation)(nil) -var _ Node = (*ParseNode)(nil) -var _ Node = (*ColumnCompat)(nil) -var _ Node = (*TopK)(nil) -var _ Node = (*Parallelize)(nil) -var _ Node = (*ScanSet)(nil) -var _ Node = (*Join)(nil) - -func (*DataObjScan) isNode() {} -func (*Projection) isNode() {} -func (*Limit) isNode() {} -func (*Filter) isNode() {} -func (*RangeAggregation) isNode() {} -func (*VectorAggregation) isNode() {} -func (*ParseNode) isNode() {} -func (*ColumnCompat) isNode() {} -func (*TopK) isNode() {} -func (*Parallelize) isNode() {} -func (*ScanSet) isNode() {} -func (*Join) isNode() {} - -// WalkOrder defines the order for how a node and its children are visited. -type WalkOrder uint8 - -const ( - // PreOrderWalk processes the current vertex before visiting any of its - // children. - PreOrderWalk WalkOrder = iota - - // PostOrderWalk processes the current vertex after visiting all of its - // children. - PostOrderWalk -) - -// Plan represents a physical execution plan as a directed acyclic graph (DAG). -// It maintains the relationships between nodes, tracking parent-child connections -// and providing methods for graph traversal and manipulation. -// -// The plan structure supports operations like adding nodes and edges, -// retrieving nodes by ID, retrieving parents and children of nodes, and -// walking the graph in different orders using the depth-first-search algorithm. -type Plan struct { - graph dag.Graph[Node] -} - -// FromGraph constructs a Plan from a given DAG. -func FromGraph(graph dag.Graph[Node]) *Plan { - return &Plan{graph: graph} -} - -// Graph returns the underlying graph of the plan. Modifications to the returned -// graph will affect the Plan. -func (p *Plan) Graph() *dag.Graph[Node] { return &p.graph } - -// Len returns the number of nodes in the graph. -func (p *Plan) Len() int { return p.graph.Len() } - -// Parent returns the parents of the given node. -func (p *Plan) Parent(n Node) []Node { return p.graph.Parents(n) } - -// Children returns all child nodes of the given node. -func (p *Plan) Children(n Node) []Node { return p.graph.Children(n) } - -// Roots returns all nodes that have no parents. -func (p *Plan) Roots() []Node { return p.graph.Roots() } - -// Root returns the root node that have no parents. It returns an error if the -// plan has no or multiple root nodes. -func (p *Plan) Root() (Node, error) { return p.graph.Root() } - -// Leaves returns all nodes that have no children. -func (p *Plan) Leaves() []Node { return p.graph.Leaves() } - -// DFSWalk performs a depth-first traversal of the plan starting from node n. -// It applies the visitor v to each node according to the specified walk order. -// The order parameter determines if nodes are visited before their children -// ([PreOrderWalk]) or after their children ([PostOrderWalk]). -func (p *Plan) DFSWalk(n Node, v Visitor, order WalkOrder) error { - return p.graph.Walk(n, func(n Node) error { return n.Accept(v) }, dag.WalkOrder(order)) -} diff --git a/pkg/engine/internal/planner/physical/planner.go b/pkg/engine/internal/planner/physical/planner.go index 077943489f472..90e4b32f0d717 100644 --- a/pkg/engine/internal/planner/physical/planner.go +++ b/pkg/engine/internal/planner/physical/planner.go @@ -8,8 +8,10 @@ import ( "time" "github.com/grafana/loki/v3/pkg/engine/internal/planner/logical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" + "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid" ) // Context carries planning state that needs to be propagated down the plan tree. @@ -23,7 +25,7 @@ type Context struct { from time.Time through time.Time rangeInterval time.Duration - direction SortOrder + direction physicalpb.SortOrder v1Compatible bool } @@ -43,7 +45,7 @@ func (pc *Context) Clone() *Context { } } -func (pc *Context) WithDirection(direction SortOrder) *Context { +func (pc *Context) WithDirection(direction physicalpb.SortOrder) *Context { cloned := pc.Clone() cloned.direction = direction return cloned @@ -77,7 +79,7 @@ func (pc *Context) GetResolveTimeRange() (from, through time.Time) { type Planner struct { context *Context catalog Catalog - plan *Plan + plan *physicalpb.Plan } // NewPlanner creates a new planner instance with the given context. @@ -90,7 +92,7 @@ func NewPlanner(ctx *Context, catalog Catalog) *Planner { // Build converts a given logical plan into a physical plan and returns an error if the conversion fails. // The resulting plan can be accessed using [Planner.Plan]. -func (p *Planner) Build(lp *logical.Plan) (*Plan, error) { +func (p *Planner) Build(lp *logical.Plan) (*physicalpb.Plan, error) { p.reset() for _, inst := range lp.Instructions { switch inst := inst.(type) { @@ -107,34 +109,34 @@ func (p *Planner) Build(lp *logical.Plan) (*Plan, error) { // reset resets the internal state of the planner func (p *Planner) reset() { - p.plan = &Plan{} + p.plan = &physicalpb.Plan{} } // Convert a predicate from an [logical.Instruction] into an [Expression]. -func (p *Planner) convertPredicate(inst logical.Value) Expression { +func (p *Planner) convertPredicate(inst logical.Value) *physicalpb.Expression { switch inst := inst.(type) { case *logical.UnaryOp: - return &UnaryExpr{ - Left: p.convertPredicate(inst.Value), - Op: inst.Op, - } + return (&physicalpb.UnaryExpression{ + Value: p.convertPredicate(inst.Value), + Op: unaryOpLogToPhys(inst.Op), + }).ToExpression() case *logical.BinOp: - return &BinaryExpr{ + return (&physicalpb.BinaryExpression{ Left: p.convertPredicate(inst.Left), Right: p.convertPredicate(inst.Right), - Op: inst.Op, - } + Op: binaryOpLogToPhys(inst.Op), + }).ToExpression() case *logical.ColumnRef: - return &ColumnExpr{Ref: inst.Ref} + return (&physicalpb.ColumnExpression{Name: inst.Ref.Column, Type: ColumnTypeLogToPhys(inst.Ref.Type)}).ToExpression() case *logical.Literal: - return NewLiteral(inst.Value()) + return NewLiteral(inst.Value()).ToExpression() default: panic(fmt.Sprintf("invalid value for predicate: %T", inst)) } } -// Convert a [logical.Instruction] into [Node]. -func (p *Planner) process(inst logical.Value, ctx *Context) (Node, error) { +// Convert a [logical.Instruction] into [physicalpb.Node]. +func (p *Planner) process(inst logical.Value, ctx *Context) (physicalpb.Node, error) { switch inst := inst.(type) { case *logical.MakeTable: return p.processMakeTable(inst, ctx) @@ -164,59 +166,61 @@ func (p *Planner) process(inst logical.Value, ctx *Context) (Node, error) { } // Convert [logical.MakeTable] into one or more [DataObjScan] nodes. -func (p *Planner) processMakeTable(lp *logical.MakeTable, ctx *Context) (Node, error) { +func (p *Planner) processMakeTable(lp *logical.MakeTable, ctx *Context) (physicalpb.Node, error) { shard, ok := lp.Shard.(*logical.ShardInfo) if !ok { return nil, fmt.Errorf("invalid shard, got %T", lp.Shard) } - predicates := make([]Expression, len(lp.Predicates)) + predicates := make([]*physicalpb.Expression, len(lp.Predicates)) for i, predicate := range lp.Predicates { predicates[i] = p.convertPredicate(predicate) } from, through := ctx.GetResolveTimeRange() - filteredShardDescriptors, err := p.catalog.ResolveShardDescriptorsWithShard(p.convertPredicate(lp.Selector), predicates, ShardInfo(*shard), from, through) + filteredShardDescriptors, err := p.catalog.ResolveShardDescriptorsWithShard(*p.convertPredicate(lp.Selector), predicates, ShardInfo(*shard), from, through) if err != nil { return nil, err } sort.Slice(filteredShardDescriptors, func(i, j int) bool { return filteredShardDescriptors[i].TimeRange.End.After(filteredShardDescriptors[j].TimeRange.End) }) - if ctx.direction == ASC { + if ctx.direction == physicalpb.SORT_ORDER_ASCENDING { slices.Reverse(filteredShardDescriptors) } // Scan work can be parallelized across multiple workers, so we wrap // everything into a single Parallelize node. - var parallelize Node = &Parallelize{} - p.plan.graph.Add(parallelize) + var parallelize physicalpb.Node = &physicalpb.Parallelize{Id: physicalpb.PlanNodeID{Value: ulid.New()}} + p.plan.Add(parallelize) - scanSet := &ScanSet{} - p.plan.graph.Add(scanSet) + scanSet := &physicalpb.ScanSet{Id: physicalpb.PlanNodeID{Value: ulid.New()}} + p.plan.Add(scanSet) for _, desc := range filteredShardDescriptors { for _, section := range desc.Sections { - scanSet.Targets = append(scanSet.Targets, &ScanTarget{ - Type: ScanTypeDataObject, - - DataObject: &DataObjScan{ - Location: desc.Location, - StreamIDs: desc.Streams, - Section: section, + scanSet.Targets = append(scanSet.Targets, &physicalpb.ScanTarget{ + Type: physicalpb.SCAN_TYPE_DATA_OBJECT, + + DataObject: &physicalpb.DataObjScan{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, + Location: string(desc.Location), + StreamIds: desc.Streams, + Section: int64(section), }, }) } } - var base Node = scanSet + var base physicalpb.Node = scanSet if p.context.v1Compatible { - compat := &ColumnCompat{ - Source: types.ColumnTypeMetadata, - Destination: types.ColumnTypeMetadata, - Collision: types.ColumnTypeLabel, + compat := &physicalpb.ColumnCompat{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, + Source: physicalpb.COLUMN_TYPE_METADATA, + Destination: physicalpb.COLUMN_TYPE_METADATA, + Collision: physicalpb.COLUMN_TYPE_LABEL, } base, err = p.wrapNodeWith(base, compat) if err != nil { @@ -226,79 +230,81 @@ func (p *Planner) processMakeTable(lp *logical.MakeTable, ctx *Context) (Node, e // Add an edge between the parallelize and the final base node (which may // have been changed after processing compatibility). - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: parallelize, Child: base}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: parallelize, Child: base}); err != nil { return nil, err } return parallelize, nil } // Convert [logical.Select] into one [Filter] node. -func (p *Planner) processSelect(lp *logical.Select, ctx *Context) (Node, error) { - node := &Filter{ - Predicates: []Expression{p.convertPredicate(lp.Predicate)}, +func (p *Planner) processSelect(lp *logical.Select, ctx *Context) (physicalpb.Node, error) { + node := &physicalpb.Filter{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, + Predicates: []*physicalpb.Expression{p.convertPredicate(lp.Predicate)}, } - p.plan.graph.Add(node) + p.plan.Add(node) child, err := p.process(lp.Table, ctx) if err != nil { return nil, err } - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: node, Child: child}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: node, Child: child}); err != nil { return nil, err } return node, nil } -// processSort processes a [logical.Sort] node. -func (p *Planner) processSort(lp *logical.Sort, ctx *Context) (Node, error) { - order := DESC +// Pass sort direction from [logical.Sort] to the children. +func (p *Planner) processSort(lp *logical.Sort, ctx *Context) (physicalpb.Node, error) { + order := physicalpb.SORT_ORDER_DESCENDING if lp.Ascending { - order = ASC + order = physicalpb.SORT_ORDER_ASCENDING } - node := &TopK{ - SortBy: &ColumnExpr{Ref: lp.Column.Ref}, - Ascending: order == ASC, + node := &physicalpb.TopK{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, + SortBy: &physicalpb.ColumnExpression{Name: lp.Column.Ref.Column, Type: ColumnTypeLogToPhys(lp.Column.Ref.Type)}, + Ascending: order == physicalpb.SORT_ORDER_ASCENDING, NullsFirst: false, - // K initially starts at 0, indicating to sort everything. The // [limitPushdown] optimization pass can update this value based on how // many rows are needed. K: 0, } - p.plan.graph.Add(node) + p.plan.Add(node) child, err := p.process(lp.Table, ctx.WithDirection(order)) if err != nil { return nil, err } - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: node, Child: child}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: node, Child: child}); err != nil { return nil, err } return node, nil } // Converts a [logical.Projection] into a physical [Projection] node. -func (p *Planner) processProjection(lp *logical.Projection, ctx *Context) (Node, error) { - expressions := make([]Expression, len(lp.Expressions)) +func (p *Planner) processProjection(lp *logical.Projection, ctx *Context) (physicalpb.Node, error) { + expressions := make([]*physicalpb.Expression, len(lp.Expressions)) for i := range lp.Expressions { expressions[i] = p.convertPredicate(lp.Expressions[i]) } - node := &Projection{ + node := &physicalpb.Projection{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, Expressions: expressions, All: lp.All, Expand: lp.Expand, Drop: lp.Drop, } - p.plan.graph.Add(node) + p.plan.Add(node) child, err := p.process(lp.Relation, ctx) if err != nil { return nil, err } - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: node, Child: child}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: node, Child: child}); err != nil { return nil, err } @@ -306,66 +312,69 @@ func (p *Planner) processProjection(lp *logical.Projection, ctx *Context) (Node, } // Convert [logical.Limit] into one [Limit] node. -func (p *Planner) processLimit(lp *logical.Limit, ctx *Context) (Node, error) { - node := &Limit{ +func (p *Planner) processLimit(lp *logical.Limit, ctx *Context) (physicalpb.Node, error) { + node := &physicalpb.Limit{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, Skip: lp.Skip, Fetch: lp.Fetch, } - p.plan.graph.Add(node) + p.plan.Add(node) child, err := p.process(lp.Table, ctx) if err != nil { return nil, err } - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: node, Child: child}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: node, Child: child}); err != nil { return nil, err } return node, nil } -func (p *Planner) processRangeAggregation(r *logical.RangeAggregation, ctx *Context) (Node, error) { - partitionBy := make([]ColumnExpression, len(r.PartitionBy)) +func (p *Planner) processRangeAggregation(r *logical.RangeAggregation, ctx *Context) (physicalpb.Node, error) { + partitionBy := make([]*physicalpb.ColumnExpression, len(r.PartitionBy)) for i, col := range r.PartitionBy { - partitionBy[i] = &ColumnExpr{Ref: col.Ref} + partitionBy[i] = &physicalpb.ColumnExpression{Name: col.Ref.Column, Type: ColumnTypeLogToPhys(col.Ref.Type)} } - node := &RangeAggregation{ - PartitionBy: partitionBy, - Operation: r.Operation, - Start: r.Start, - End: r.End, - Range: r.RangeInterval, - Step: r.Step, + node := &physicalpb.AggregateRange{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, + PartitionBy: partitionBy, + Operation: rangeAggregationTypeLogToPhys(r.Operation), + StartUnixNanos: r.Start.UnixNano(), + EndUnixNanos: r.End.UnixNano(), + RangeNs: r.RangeInterval.Nanoseconds(), + StepNs: r.Step.Nanoseconds(), } - p.plan.graph.Add(node) + p.plan.Add(node) child, err := p.process(r.Table, ctx.WithRangeInterval(r.RangeInterval)) if err != nil { return nil, err } - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: node, Child: child}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: node, Child: child}); err != nil { return nil, err } return node, nil } // Convert [logical.VectorAggregation] into one [VectorAggregation] node. -func (p *Planner) processVectorAggregation(lp *logical.VectorAggregation, ctx *Context) (Node, error) { - groupBy := make([]ColumnExpression, len(lp.GroupBy)) +func (p *Planner) processVectorAggregation(lp *logical.VectorAggregation, ctx *Context) (physicalpb.Node, error) { + groupBy := make([]*physicalpb.ColumnExpression, len(lp.GroupBy)) for i, col := range lp.GroupBy { - groupBy[i] = &ColumnExpr{Ref: col.Ref} + groupBy[i] = &physicalpb.ColumnExpression{Name: col.Ref.Column, Type: ColumnTypeLogToPhys(col.Ref.Type)} } - node := &VectorAggregation{ + node := &physicalpb.AggregateVector{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, GroupBy: groupBy, - Operation: lp.Operation, + Operation: vectorAggregationTypeLogToPhys(lp.Operation), } - p.plan.graph.Add(node) + p.plan.Add(node) child, err := p.process(lp.Table, ctx) if err != nil { return nil, err } - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: node, Child: child}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: node, Child: child}); err != nil { return nil, err } return node, nil @@ -382,18 +391,18 @@ func (p *Planner) processVectorAggregation(lp *logical.VectorAggregation, ctx *C // Return: // - acc: currently accumulated expression. // - input: a physical plan node of the only input of that expression, if any. -// - inputRef: a pointer to a node in `acc` that refers the input, if any. This is for convenience of +// - inputExpr: a pointer to a node in `acc` that refers the input, if any. This is for convenience of // renaming the column refenrece without a need to search for it in `acc` expression. // - err: error -func (p *Planner) collapseMathExpressions(lp logical.Value, rootNode bool, ctx *Context) (acc Expression, input Node, inputRef *ColumnExpr, err error) { +func (p *Planner) collapseMathExpressions(lp logical.Value, rootNode bool, ctx *Context) (acc *physicalpb.Expression, input physicalpb.Node, inputRef *physicalpb.ColumnExpression, err error) { switch v := lp.(type) { case *logical.BinOp: // Traverse left and right children - leftChild, leftInput, leftInputRef, err := p.collapseMathExpressions(v.Left, false, ctx) + leftChild, leftInput, leftInputExpr, err := p.collapseMathExpressions(v.Left, false, ctx) if err != nil { return nil, nil, nil, err } - rightChild, rightInput, rightInputRef, err := p.collapseMathExpressions(v.Right, false, ctx) + rightChild, rightInput, rightInputExpr, err := p.collapseMathExpressions(v.Right, false, ctx) if err != nil { return nil, nil, nil, err } @@ -401,127 +410,125 @@ func (p *Planner) collapseMathExpressions(lp logical.Value, rootNode bool, ctx * // Both left and right expressions have obj scans, replace with join if leftInput != nil && rightInput != nil { // Replace column references with `_left` and `_right` indicating that there are two inputs coming from a Join - leftInputRef.Ref = types.ColumnRef{ - Column: "value_left", - Type: types.ColumnTypeGenerated, - } - rightInputRef.Ref = types.ColumnRef{ - Column: "value_right", - Type: types.ColumnTypeGenerated, - } + leftInputExpr.Name = "value_left" + leftInputExpr.Type = physicalpb.COLUMN_TYPE_GENERATED + rightInputExpr.Name = "value_right" + rightInputExpr.Type = physicalpb.COLUMN_TYPE_GENERATED // Insert an InnerJoin on timestamp before Projection - join := &Join{} - p.plan.graph.Add(join) + join := &physicalpb.Join{Id: physicalpb.PlanNodeID{Value: ulid.New()}} + p.plan.Add(join) - projection := &Projection{ - Expressions: []Expression{ - &BinaryExpr{ + projection := &physicalpb.Projection{ + Expressions: []*physicalpb.Expression{ + (&physicalpb.BinaryExpression{ Left: leftChild, Right: rightChild, - Op: v.Op, - }, + Op: binaryOpLogToPhys(v.Op), + }).ToExpression(), }, All: true, Expand: true, } - p.plan.graph.Add(projection) + p.plan.Add(projection) // Connect the join to the projection - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: projection, Child: join}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: projection, Child: join}); err != nil { return nil, nil, nil, err } // Connect left and right children to the join - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: join, Child: leftInput}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: join, Child: leftInput}); err != nil { return nil, nil, nil, err } - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: join, Child: rightInput}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: join, Child: rightInput}); err != nil { return nil, nil, nil, err } // Result of this math expression returns `value` column - columnRef := newColumnExpr(types.ColumnNameGeneratedValue, types.ColumnTypeGenerated) + columnRef := newColumnExpr(types.ColumnNameGeneratedValue, physicalpb.COLUMN_TYPE_GENERATED) - return columnRef, join, columnRef, nil + return columnRef.ToExpression(), join, columnRef, nil } - // Eigther left or right expression has an obj scan. Pick the non-nil one. + // Either left or right expression has an obj scan. Pick the non-nil one. input := leftInput if leftInput == nil { input = rightInput } - inputRef := leftInputRef - if leftInputRef == nil { - inputRef = rightInputRef + inputExpr := leftInputExpr + if leftInputExpr == nil { + inputExpr = rightInputExpr } - expr := &BinaryExpr{ + expr := &physicalpb.BinaryExpression{ Left: leftChild, Right: rightChild, - Op: v.Op, + Op: binaryOpLogToPhys(v.Op), } // we have to stop here and produce a Node, otherwise keep collapsing if rootNode { - projection := &Projection{ - Expressions: []Expression{expr}, + projection := &physicalpb.Projection{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, + Expressions: []*physicalpb.Expression{expr.ToExpression()}, All: true, Expand: true, } - p.plan.graph.Add(projection) - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: projection, Child: input}); err != nil { + p.plan.Add(projection) + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: projection, Child: input}); err != nil { return nil, nil, nil, err } - columnRef := newColumnExpr(types.ColumnNameGeneratedValue, types.ColumnTypeGenerated) + columnRef := newColumnExpr(types.ColumnNameGeneratedValue, physicalpb.COLUMN_TYPE_GENERATED) - return columnRef, projection, columnRef, nil + return columnRef.ToExpression(), projection, columnRef, nil } - return expr, input, inputRef, nil + return expr.ToExpression(), input, inputExpr, nil case *logical.UnaryOp: - child, input, inputRef, err := p.collapseMathExpressions(v.Value, false, ctx) + child, input, inputExpr, err := p.collapseMathExpressions(v.Value, false, ctx) if err != nil { return nil, nil, nil, err } - expr := &UnaryExpr{ - Left: child, - Op: v.Op, + expr := &physicalpb.UnaryExpression{ + Value: child, + Op: unaryOpLogToPhys(v.Op), } if rootNode { - projection := &Projection{ - Expressions: []Expression{expr}, + projection := &physicalpb.Projection{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, + Expressions: []*physicalpb.Expression{expr.ToExpression()}, All: true, Expand: true, } - p.plan.graph.Add(projection) - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: projection, Child: input}); err != nil { + p.plan.Add(projection) + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: projection, Child: input}); err != nil { return nil, nil, nil, err } - columnRef := newColumnExpr(types.ColumnNameGeneratedValue, types.ColumnTypeGenerated) + columnRef := newColumnExpr(types.ColumnNameGeneratedValue, physicalpb.COLUMN_TYPE_GENERATED) - return columnRef, projection, columnRef, nil + return columnRef.ToExpression(), projection, columnRef, nil } - return expr, input, inputRef, nil + return expr.ToExpression(), input, inputExpr, nil case *logical.Literal: - return &LiteralExpr{Literal: v.Literal}, nil, nil, nil + return NewLiteral(v.Value()).ToExpression(), nil, nil, nil default: // If it is neigher a literal nor an expression, then we continue `p.process` on this node and represent in // as a column ref `value` in the final math expression. - columnRef := newColumnExpr(types.ColumnNameGeneratedValue, types.ColumnTypeGenerated) + columnExpr := newColumnExpr(types.ColumnNameGeneratedValue, physicalpb.COLUMN_TYPE_GENERATED) child, err := p.process(lp, ctx) if err != nil { return nil, nil, nil, err } - return columnRef, child, columnRef, nil + return columnExpr.ToExpression(), child, columnExpr, nil } } // Convert one or several [logical.BinOp]s into one [Projection] node where the result expression might be complex with // multiple binary or unary operations. It also might insert a [Join] node before a [Projection] if this math expression // reads data on both left and right sides. -func (p *Planner) processBinOp(lp *logical.BinOp, ctx *Context) (Node, error) { +func (p *Planner) processBinOp(lp *logical.BinOp, ctx *Context) (physicalpb.Node, error) { _, node, _, err := p.collapseMathExpressions(lp, true, ctx) if err != nil { return nil, err @@ -533,7 +540,7 @@ func (p *Planner) processBinOp(lp *logical.BinOp, ctx *Context) (Node, error) { // Convert one or several [logical.UnaryOp]s into one [Projection] node where the result expression might be complex with // multiple binary or unary operations. It also might insert a [Join] node before a [Projection] if this math expression // reads data on both left and right sides. -func (p *Planner) processUnaryOp(lp *logical.UnaryOp, ctx *Context) (Node, error) { +func (p *Planner) processUnaryOp(lp *logical.UnaryOp, ctx *Context) (physicalpb.Node, error) { _, node, _, err := p.collapseMathExpressions(lp, true, ctx) if err != nil { return nil, err @@ -544,26 +551,28 @@ func (p *Planner) processUnaryOp(lp *logical.UnaryOp, ctx *Context) (Node, error // Convert [logical.Parse] into one [ParseNode] node. // A ParseNode initially has an empty list of RequestedKeys which will be populated during optimization. -func (p *Planner) processParse(lp *logical.Parse, ctx *Context) (Node, error) { - var node Node = &ParseNode{ - Kind: convertParserKind(lp.Kind), +func (p *Planner) processParse(lp *logical.Parse, ctx *Context) (physicalpb.Node, error) { + var node physicalpb.Node = &physicalpb.Parse{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, + Operation: convertParserKind(lp.Kind), } - p.plan.graph.Add(node) + p.plan.Add(node) child, err := p.process(lp.Table, ctx) if err != nil { return nil, err } - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: node, Child: child}); err != nil { + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: node, Child: child}); err != nil { return nil, err } if p.context.v1Compatible { - compat := &ColumnCompat{ - Source: types.ColumnTypeParsed, - Destination: types.ColumnTypeParsed, - Collision: types.ColumnTypeLabel, + compat := &physicalpb.ColumnCompat{ + Id: physicalpb.PlanNodeID{Value: ulid.New()}, + Source: physicalpb.COLUMN_TYPE_PARSED, + Destination: physicalpb.COLUMN_TYPE_PARSED, + Collision: physicalpb.COLUMN_TYPE_LABEL, } node, err = p.wrapNodeWith(node, compat) if err != nil { @@ -574,9 +583,9 @@ func (p *Planner) processParse(lp *logical.Parse, ctx *Context) (Node, error) { return node, nil } -func (p *Planner) wrapNodeWith(node Node, wrapper Node) (Node, error) { - p.plan.graph.Add(wrapper) - if err := p.plan.graph.AddEdge(dag.Edge[Node]{Parent: wrapper, Child: node}); err != nil { +func (p *Planner) wrapNodeWith(node physicalpb.Node, wrapper physicalpb.Node) (physicalpb.Node, error) { + p.plan.Add(wrapper) + if err := p.plan.AddEdge(dag.Edge[physicalpb.Node]{Parent: wrapper, Child: node}); err != nil { return nil, err } return wrapper, nil @@ -584,7 +593,7 @@ func (p *Planner) wrapNodeWith(node Node, wrapper Node) (Node, error) { // Optimize runs optimization passes over the plan, modifying it // if any optimizations can be applied. -func (p *Planner) Optimize(plan *Plan) (*Plan, error) { +func (p *Planner) Optimize(plan *physicalpb.Plan) (*physicalpb.Plan, error) { for i, root := range plan.Roots() { optimizations := []*optimization{ newOptimization("PredicatePushdown", plan).withRules( @@ -617,13 +626,147 @@ func (p *Planner) Optimize(plan *Plan) (*Plan, error) { return plan, nil } -func convertParserKind(kind logical.ParserKind) ParserKind { +func convertParserKind(kind logical.ParserKind) physicalpb.ParseOp { switch kind { case logical.ParserLogfmt: - return ParserLogfmt + return physicalpb.PARSE_OP_LOGFMT case logical.ParserJSON: - return ParserJSON + return physicalpb.PARSE_OP_JSON + default: + return physicalpb.PARSE_OP_INVALID + } +} + +func unaryOpLogToPhys(op types.UnaryOp) physicalpb.UnaryOp { + switch op { + case types.UnaryOpAbs: + return physicalpb.UNARY_OP_ABS + case types.UnaryOpCastBytes: + return physicalpb.UNARY_OP_CAST_BYTES + case types.UnaryOpCastDuration: + return physicalpb.UNARY_OP_CAST_DURATION + case types.UnaryOpCastFloat: + return physicalpb.UNARY_OP_CAST_FLOAT + case types.UnaryOpNot: + return physicalpb.UNARY_OP_NOT + default: + return physicalpb.UNARY_OP_INVALID + } +} + +func binaryOpLogToPhys(op types.BinaryOp) physicalpb.BinaryOp { + switch op { + case types.BinaryOpEq: + return physicalpb.BINARY_OP_EQ + case types.BinaryOpNeq: + return physicalpb.BINARY_OP_NEQ + case types.BinaryOpGt: + return physicalpb.BINARY_OP_GT + case types.BinaryOpGte: + return physicalpb.BINARY_OP_GTE + case types.BinaryOpLt: + return physicalpb.BINARY_OP_LT + case types.BinaryOpLte: + return physicalpb.BINARY_OP_LTE + + case types.BinaryOpAnd: + return physicalpb.BINARY_OP_AND + case types.BinaryOpOr: + return physicalpb.BINARY_OP_OR + case types.BinaryOpXor: + return physicalpb.BINARY_OP_XOR + case types.BinaryOpNot: + return physicalpb.BINARY_OP_NOT + + case types.BinaryOpAdd: + return physicalpb.BINARY_OP_ADD + case types.BinaryOpSub: + return physicalpb.BINARY_OP_SUB + case types.BinaryOpMul: + return physicalpb.BINARY_OP_MUL + case types.BinaryOpDiv: + return physicalpb.BINARY_OP_DIV + case types.BinaryOpMod: + return physicalpb.BINARY_OP_MOD + case types.BinaryOpPow: + return physicalpb.BINARY_OP_POW + + case types.BinaryOpMatchSubstr: + return physicalpb.BINARY_OP_MATCH_SUBSTR + case types.BinaryOpNotMatchSubstr: + return physicalpb.BINARY_OP_NOT_MATCH_SUBSTR + case types.BinaryOpMatchRe: + return physicalpb.BINARY_OP_MATCH_RE + case types.BinaryOpNotMatchRe: + return physicalpb.BINARY_OP_NOT_MATCH_RE + case types.BinaryOpMatchPattern: + return physicalpb.BINARY_OP_MATCH_PATTERN + case types.BinaryOpNotMatchPattern: + return physicalpb.BINARY_OP_NOT_MATCH_PATTERN + default: + return physicalpb.BINARY_OP_INVALID + } +} + +func ColumnTypeLogToPhys(colType types.ColumnType) physicalpb.ColumnType { + switch colType { + case types.ColumnTypeBuiltin: + return physicalpb.COLUMN_TYPE_BUILTIN + case types.ColumnTypeLabel: + return physicalpb.COLUMN_TYPE_LABEL + case types.ColumnTypeMetadata: + return physicalpb.COLUMN_TYPE_METADATA + case types.ColumnTypeParsed: + return physicalpb.COLUMN_TYPE_PARSED + case types.ColumnTypeAmbiguous: + return physicalpb.COLUMN_TYPE_AMBIGUOUS + case types.ColumnTypeGenerated: + return physicalpb.COLUMN_TYPE_GENERATED + default: + return physicalpb.COLUMN_TYPE_INVALID + } +} + +func rangeAggregationTypeLogToPhys(rangeAggType types.RangeAggregationType) physicalpb.AggregateRangeOp { + switch rangeAggType { + case types.RangeAggregationTypeCount: + return physicalpb.AGGREGATE_RANGE_OP_COUNT + case types.RangeAggregationTypeSum: + return physicalpb.AGGREGATE_RANGE_OP_SUM + case types.RangeAggregationTypeMax: + return physicalpb.AGGREGATE_RANGE_OP_MAX + case types.RangeAggregationTypeMin: + return physicalpb.AGGREGATE_RANGE_OP_MIN + default: + return physicalpb.AGGREGATE_RANGE_OP_INVALID + } +} + +func vectorAggregationTypeLogToPhys(vectorAggType types.VectorAggregationType) physicalpb.AggregateVectorOp { + switch vectorAggType { + case types.VectorAggregationTypeSum: + return physicalpb.AGGREGATE_VECTOR_OP_SUM + case types.VectorAggregationTypeMax: + return physicalpb.AGGREGATE_VECTOR_OP_MAX + case types.VectorAggregationTypeMin: + return physicalpb.AGGREGATE_VECTOR_OP_MIN + case types.VectorAggregationTypeCount: + return physicalpb.AGGREGATE_VECTOR_OP_COUNT + case types.VectorAggregationTypeAvg: + return physicalpb.AGGREGATE_VECTOR_OP_AVG + case types.VectorAggregationTypeStddev: + return physicalpb.AGGREGATE_VECTOR_OP_STDDEV + case types.VectorAggregationTypeStdvar: + return physicalpb.AGGREGATE_VECTOR_OP_STDVAR + case types.VectorAggregationTypeBottomK: + return physicalpb.AGGREGATE_VECTOR_OP_BOTTOMK + case types.VectorAggregationTypeTopK: + return physicalpb.AGGREGATE_VECTOR_OP_TOPK + case types.VectorAggregationTypeSort: + return physicalpb.AGGREGATE_VECTOR_OP_SORT + case types.VectorAggregationTypeSortDesc: + return physicalpb.AGGREGATE_VECTOR_OP_SORT_DESC default: - return ParserInvalid + return physicalpb.AGGREGATE_VECTOR_OP_INVALID } } diff --git a/pkg/engine/internal/planner/physical/planner_test.go b/pkg/engine/internal/planner/physical/planner_test.go index 18afa57eefa51..1826d9d170d0d 100644 --- a/pkg/engine/internal/planner/physical/planner_test.go +++ b/pkg/engine/internal/planner/physical/planner_test.go @@ -9,8 +9,10 @@ import ( "github.com/grafana/loki/v3/pkg/dataobj/metastore" "github.com/grafana/loki/v3/pkg/engine/internal/planner/logical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" + "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid" ) type catalog struct { @@ -18,12 +20,12 @@ type catalog struct { } // ResolveShardDescriptors implements Catalog. -func (c *catalog) ResolveShardDescriptors(e Expression, from, through time.Time) ([]FilteredShardDescriptor, error) { +func (c *catalog) ResolveShardDescriptors(e physicalpb.Expression, from, through time.Time) ([]FilteredShardDescriptor, error) { return c.ResolveShardDescriptorsWithShard(e, nil, noShard, from, through) } // ResolveDataObjForShard implements Catalog. -func (c *catalog) ResolveShardDescriptorsWithShard(_ Expression, _ []Expression, shard ShardInfo, _, _ time.Time) ([]FilteredShardDescriptor, error) { +func (c *catalog) ResolveShardDescriptorsWithShard(_ physicalpb.Expression, _ []*physicalpb.Expression, shard ShardInfo, _, _ time.Time) ([]FilteredShardDescriptor, error) { return filterDescriptorsForShard(shard, c.sectionDescriptors) } @@ -79,48 +81,48 @@ func TestMockCatalog(t *testing.T) { }, } { t.Run("shard "+tt.shard.String(), func(t *testing.T) { - filteredShardDescriptors, err := catalog.ResolveShardDescriptorsWithShard(nil, nil, tt.shard, timeStart, timeEnd) + filteredShardDescriptors, err := catalog.ResolveShardDescriptorsWithShard(physicalpb.Expression{}, nil, tt.shard, timeStart, timeEnd) require.Nil(t, err) require.ElementsMatch(t, tt.expDescriptors, filteredShardDescriptors) }) } } -func locations(t *testing.T, plan *Plan, node Node) []string { +func locations(t *testing.T, plan *physicalpb.Plan, node physicalpb.Node) []string { res := make([]string, 0) visitor := &nodeCollectVisitor{ - onVisitScanSet: func(set *ScanSet) error { + onVisitScanSet: func(set *physicalpb.ScanSet) error { for _, target := range set.Targets { switch target.Type { - case ScanTypeDataObject: - res = append(res, string(target.DataObject.Location)) + case physicalpb.SCAN_TYPE_DATA_OBJECT: + res = append(res, target.DataObject.Location) } } return nil }, } - require.NoError(t, plan.DFSWalk(node, visitor, PreOrderWalk)) + require.NoError(t, plan.VisitorWalk(node, visitor, physicalpb.PRE_ORDER_WALK)) return res } -func sections(t *testing.T, plan *Plan, node Node) [][]int { +func sections(t *testing.T, plan *physicalpb.Plan, node physicalpb.Node) [][]int { res := make([][]int, 0) visitor := &nodeCollectVisitor{ - onVisitScanSet: func(set *ScanSet) error { + onVisitScanSet: func(set *physicalpb.ScanSet) error { for _, target := range set.Targets { switch target.Type { - case ScanTypeDataObject: - res = append(res, []int{target.DataObject.Section}) + case physicalpb.SCAN_TYPE_DATA_OBJECT: + res = append(res, []int{int(target.DataObject.Section)}) } } return nil }, } - require.NoError(t, plan.DFSWalk(node, visitor, PreOrderWalk)) + require.NoError(t, plan.VisitorWalk(node, visitor, physicalpb.PRE_ORDER_WALK)) return res } @@ -302,22 +304,22 @@ func TestPlanner_Convert_WithParse(t *testing.T) { require.NoError(t, err) // Physical plan is built bottom up, so it should be Filter -> ParseNode -> ... - filterNode, ok := root.(*Filter) + filterNode, ok := root.(*physicalpb.Filter) require.True(t, ok, "Root should be Filter") children := physicalPlan.Children(filterNode) require.Len(t, children, 1) - compatNode, ok := children[0].(*ColumnCompat) + compatNode, ok := children[0].(*physicalpb.ColumnCompat) require.True(t, ok, "Filter's child should be ColumnCompat") - require.Equal(t, types.ColumnTypeParsed, compatNode.Source) + require.Equal(t, physicalpb.COLUMN_TYPE_PARSED, compatNode.Source) children = physicalPlan.Children(compatNode) require.Len(t, children, 1) - parseNode, ok := children[0].(*ParseNode) + parseNode, ok := children[0].(*physicalpb.Parse) require.True(t, ok, "ColumnCompat's child should be ParseNode") - require.Equal(t, ParserLogfmt, parseNode.Kind) + require.Equal(t, physicalpb.PARSE_OP_LOGFMT, parseNode.Operation) require.Empty(t, parseNode.RequestedKeys) physicalPlan, err = planner.Optimize(physicalPlan) @@ -375,20 +377,20 @@ func TestPlanner_Convert_WithParse(t *testing.T) { require.NoError(t, err) // Find ParseNode in the plan - var parseNode *ParseNode + var parseNode *physicalpb.Parse visitor := &nodeCollectVisitor{ - onVisitParse: func(node *ParseNode) error { + onVisitParse: func(node *physicalpb.Parse) error { parseNode = node return nil }, } root, err := physicalPlan.Root() require.NoError(t, err) - err = physicalPlan.DFSWalk(root, visitor, PreOrderWalk) + err = physicalPlan.VisitorWalk(root, visitor, physicalpb.PRE_ORDER_WALK) require.NoError(t, err) require.NotNil(t, parseNode, "ParseNode should exist in the plan") - require.Equal(t, ParserLogfmt, parseNode.Kind) + require.Equal(t, physicalpb.PARSE_OP_LOGFMT, parseNode.Operation) require.Empty(t, parseNode.RequestedKeys) // Before optimization physicalPlan, err = planner.Optimize(physicalPlan) @@ -436,7 +438,7 @@ func TestPlanner_Convert_WithCastProjection(t *testing.T) { require.NoError(t, err) // Root should be a Projection node with the unwrap cast operation - projectionNode, ok := root.(*Projection) + projectionNode, ok := root.(*physicalpb.Projection) require.True(t, ok, "Root should be Projection") require.NotEmpty(t, projectionNode.Expressions, "Projection should have expressions") @@ -729,28 +731,36 @@ func TestPlanner_MakeTable_Ordering(t *testing.T) { require.NoError(t, err) t.Run("ascending", func(t *testing.T) { - planner := NewPlanner(NewContext(time.Now(), time.Now()).WithDirection(ASC), catalog) + parallelizeID := physicalpb.PlanNodeID{Value: ulid.New()} + compatID := physicalpb.PlanNodeID{Value: ulid.New()} + scanSetID := physicalpb.PlanNodeID{Value: ulid.New()} + scan1ID := physicalpb.PlanNodeID{Value: ulid.New()} + scan2ID := physicalpb.PlanNodeID{Value: ulid.New()} + scan3ID := physicalpb.PlanNodeID{Value: ulid.New()} + scan4ID := physicalpb.PlanNodeID{Value: ulid.New()} + + planner := NewPlanner(NewContext(time.Now(), time.Now()).WithDirection(physicalpb.SORT_ORDER_ASCENDING), catalog) plan, err := planner.Build(logicalPlan) require.NoError(t, err) - expectedPlan := &Plan{} - parallelize := expectedPlan.graph.Add(&Parallelize{id: "parallelize"}) - compat := expectedPlan.graph.Add(&ColumnCompat{id: "compat", Source: types.ColumnTypeMetadata, Destination: types.ColumnTypeMetadata, Collision: types.ColumnTypeLabel}) - scanSet := expectedPlan.graph.Add(&ScanSet{ - id: "scanset", + expectedPlan := &physicalpb.Plan{} + parallelize := expectedPlan.Add(&physicalpb.Parallelize{Id: parallelizeID}) + compat := expectedPlan.Add(&physicalpb.ColumnCompat{Id: compatID, Source: physicalpb.COLUMN_TYPE_METADATA, Destination: physicalpb.COLUMN_TYPE_METADATA, Collision: physicalpb.COLUMN_TYPE_LABEL}) + scanSet := expectedPlan.Add(&physicalpb.ScanSet{ + Id: scanSetID, // Targets should be added in the order of the scan timestamps // ASC => oldest to newest - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{id: "scan4", Location: "obj3", Section: 3, StreamIDs: []int64{5, 1}}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{id: "scan3", Location: "obj3", Section: 2, StreamIDs: []int64{5, 1}}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{id: "scan2", Location: "obj2", Section: 1, StreamIDs: []int64{3, 4}}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{id: "scan1", Location: "obj1", Section: 3, StreamIDs: []int64{1, 2}}}, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Id: scan4ID, Location: "obj3", Section: 3, StreamIds: []int64{5, 1}}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Id: scan3ID, Location: "obj3", Section: 2, StreamIds: []int64{5, 1}}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Id: scan2ID, Location: "obj2", Section: 1, StreamIds: []int64{3, 4}}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Id: scan1ID, Location: "obj1", Section: 3, StreamIds: []int64{1, 2}}}, }, }) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: parallelize, Child: compat}) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: compat, Child: scanSet}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parallelize), Child: physicalpb.GetNode(compat)}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(compat), Child: physicalpb.GetNode(scanSet)}) actual := PrintAsTree(plan) expected := PrintAsTree(expectedPlan) @@ -763,27 +773,34 @@ func TestPlanner_MakeTable_Ordering(t *testing.T) { }) t.Run("descending", func(t *testing.T) { - planner := NewPlanner(NewContext(time.Now(), time.Now()).WithDirection(DESC), catalog) + parallelizeID := physicalpb.PlanNodeID{Value: ulid.New()} + compatID := physicalpb.PlanNodeID{Value: ulid.New()} + scanSetID := physicalpb.PlanNodeID{Value: ulid.New()} + scan1ID := physicalpb.PlanNodeID{Value: ulid.New()} + scan2ID := physicalpb.PlanNodeID{Value: ulid.New()} + scan3ID := physicalpb.PlanNodeID{Value: ulid.New()} + scan4ID := physicalpb.PlanNodeID{Value: ulid.New()} + planner := NewPlanner(NewContext(time.Now(), time.Now()).WithDirection(physicalpb.SORT_ORDER_DESCENDING), catalog) plan, err := planner.Build(logicalPlan) require.NoError(t, err) - expectedPlan := &Plan{} - parallelize := expectedPlan.graph.Add(&Parallelize{id: "parallelize"}) - compat := expectedPlan.graph.Add(&ColumnCompat{id: "compat", Source: types.ColumnTypeMetadata, Destination: types.ColumnTypeMetadata, Collision: types.ColumnTypeLabel}) - scanSet := expectedPlan.graph.Add(&ScanSet{ - id: "scanset", + expectedPlan := &physicalpb.Plan{} + parallelize := expectedPlan.Add(&physicalpb.Parallelize{Id: parallelizeID}) + compat := expectedPlan.Add(&physicalpb.ColumnCompat{Id: compatID, Source: physicalpb.COLUMN_TYPE_METADATA, Destination: physicalpb.COLUMN_TYPE_METADATA, Collision: physicalpb.COLUMN_TYPE_LABEL}) + scanSet := expectedPlan.Add(&physicalpb.ScanSet{ + Id: scanSetID, // Targets should be added in the order of the scan timestamps - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{id: "scan1", Location: "obj1", Section: 3, StreamIDs: []int64{1, 2}}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{id: "scan2", Location: "obj2", Section: 1, StreamIDs: []int64{3, 4}}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{id: "scan3", Location: "obj3", Section: 2, StreamIDs: []int64{5, 1}}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{id: "scan4", Location: "obj3", Section: 3, StreamIDs: []int64{5, 1}}}, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Id: scan1ID, Location: "obj1", Section: 3, StreamIds: []int64{1, 2}}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Id: scan2ID, Location: "obj2", Section: 1, StreamIds: []int64{3, 4}}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Id: scan3ID, Location: "obj3", Section: 2, StreamIds: []int64{5, 1}}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Id: scan4ID, Location: "obj3", Section: 3, StreamIds: []int64{5, 1}}}, }, }) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: parallelize, Child: compat}) - _ = expectedPlan.graph.AddEdge(dag.Edge[Node]{Parent: compat, Child: scanSet}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(parallelize), Child: physicalpb.GetNode(compat)}) + _ = expectedPlan.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(compat), Child: physicalpb.GetNode(scanSet)}) actual := PrintAsTree(plan) expected := PrintAsTree(expectedPlan) diff --git a/pkg/engine/internal/planner/physical/printer.go b/pkg/engine/internal/planner/physical/printer.go index 26dadf0b3d2fa..5b6815395cc69 100644 --- a/pkg/engine/internal/planner/physical/printer.go +++ b/pkg/engine/internal/planner/physical/printer.go @@ -6,16 +6,17 @@ import ( "strings" "time" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/util/tree" ) // BuildTree converts a physical plan node and its children into a tree structure // that can be used for visualization and debugging purposes. -func BuildTree(p *Plan, n Node) *tree.Node { +func BuildTree(p *physicalpb.Plan, n physicalpb.Node) *tree.Node { return toTree(p, n) } -func toTree(p *Plan, n Node) *tree.Node { +func toTree(p *physicalpb.Plan, n physicalpb.Node) *tree.Node { root := toTreeNode(n) for _, child := range p.Children(n) { if ch := toTree(p, child); ch != nil { @@ -25,22 +26,29 @@ func toTree(p *Plan, n Node) *tree.Node { return root } -func toTreeNode(n Node) *tree.Node { - treeNode := tree.NewNode(n.Type().String(), "") +func toTreeNode(n physicalpb.Node) *tree.Node { + treeNode := tree.NewNode(n.Kind().String(), "") treeNode.Context = n switch node := n.(type) { - case *DataObjScan: + case *physicalpb.DataObjScan: treeNode.Properties = []tree.Property{ tree.NewProperty("location", false, node.Location), - tree.NewProperty("streams", false, len(node.StreamIDs)), + tree.NewProperty("streams", false, len(node.StreamIds)), tree.NewProperty("section_id", false, node.Section), tree.NewProperty("projections", true, toAnySlice(node.Projections)...), + tree.NewProperty("direction", false, node.SortOrder), + tree.NewProperty("limit", false, node.Limit), } for i := range node.Predicates { treeNode.Properties = append(treeNode.Properties, tree.NewProperty(fmt.Sprintf("predicate[%d]", i), false, node.Predicates[i].String())) } - case *Projection: + case *physicalpb.SortMerge: + treeNode.Properties = []tree.Property{ + tree.NewProperty("column", false, node.Column), + tree.NewProperty("order", false, node.Order), + } + case *physicalpb.Projection: treeNode.Properties = []tree.Property{ tree.NewProperty("all", false, node.All), } @@ -49,22 +57,24 @@ func toTreeNode(n Node) *tree.Node { } else if node.Drop { treeNode.Properties = append(treeNode.Properties, tree.NewProperty("drop", true, toAnySlice(node.Expressions)...)) } - case *Filter: + case *physicalpb.Filter: for i := range node.Predicates { treeNode.Properties = append(treeNode.Properties, tree.NewProperty(fmt.Sprintf("predicate[%d]", i), false, node.Predicates[i].String())) } - case *Limit: + case *physicalpb.Merge: + // nothing to add + case *physicalpb.Limit: treeNode.Properties = []tree.Property{ tree.NewProperty("offset", false, node.Skip), tree.NewProperty("limit", false, node.Fetch), } - case *RangeAggregation: + case *physicalpb.AggregateRange: properties := []tree.Property{ tree.NewProperty("operation", false, node.Operation), - tree.NewProperty("start", false, node.Start.Format(time.RFC3339Nano)), - tree.NewProperty("end", false, node.End.Format(time.RFC3339Nano)), - tree.NewProperty("step", false, node.Step), - tree.NewProperty("range", false, node.Range), + tree.NewProperty("start", false, time.Unix(0, node.StartUnixNanos).UTC().Format(time.RFC3339Nano)), + tree.NewProperty("end", false, time.Unix(0, node.EndUnixNanos).UTC().Format(time.RFC3339Nano)), + tree.NewProperty("step", false, time.Duration(node.StepNs)), + tree.NewProperty("range", false, time.Duration(node.RangeNs)), } if len(node.PartitionBy) > 0 { @@ -72,7 +82,7 @@ func toTreeNode(n Node) *tree.Node { } treeNode.Properties = properties - case *VectorAggregation: + case *physicalpb.AggregateVector: treeNode.Properties = []tree.Property{ tree.NewProperty("operation", false, node.Operation), } @@ -80,29 +90,29 @@ func toTreeNode(n Node) *tree.Node { if len(node.GroupBy) > 0 { treeNode.Properties = append(treeNode.Properties, tree.NewProperty("group_by", true, toAnySlice(node.GroupBy)...)) } - case *ParseNode: + case *physicalpb.Parse: treeNode.Properties = []tree.Property{ - tree.NewProperty("kind", false, node.Kind.String()), + tree.NewProperty("kind", false, node.Operation.String()), } if len(node.RequestedKeys) > 0 { treeNode.Properties = append(treeNode.Properties, tree.NewProperty("requested_keys", true, toAnySlice(node.RequestedKeys)...)) } - case *ColumnCompat: + case *physicalpb.ColumnCompat: treeNode.Properties = []tree.Property{ tree.NewProperty("src", false, node.Source), tree.NewProperty("dst", false, node.Destination), tree.NewProperty("collision", false, node.Collision), } - case *TopK: + case *physicalpb.TopK: treeNode.Properties = []tree.Property{ tree.NewProperty("sort_by", false, node.SortBy.String()), tree.NewProperty("ascending", false, node.Ascending), tree.NewProperty("nulls_first", false, node.NullsFirst), tree.NewProperty("k", false, node.K), } - case *Parallelize: + case *physicalpb.Parallelize: // Nothing to add - case *ScanSet: + case *physicalpb.ScanSet: treeNode.Properties = []tree.Property{ tree.NewProperty("num_targets", false, len(node.Targets)), } @@ -120,7 +130,7 @@ func toTreeNode(n Node) *tree.Node { } switch target.Type { - case ScanTypeDataObject: + case physicalpb.SCAN_TYPE_DATA_OBJECT: // Create a child node to extract the properties of the target. childNode := toTreeNode(target.DataObject) properties = append(properties, childNode.Properties...) @@ -143,7 +153,7 @@ func toAnySlice[T any](s []T) []any { // PrintAsTree converts a physical [Plan] into a human-readable tree representation. // It processes each root node in the plan graph, and returns the combined // string output of all trees joined by newlines. -func PrintAsTree(p *Plan) string { +func PrintAsTree(p *physicalpb.Plan) string { results := make([]string, 0, len(p.Roots())) for _, root := range p.Roots() { @@ -157,7 +167,7 @@ func PrintAsTree(p *Plan) string { return strings.Join(results, "\n") } -func WriteMermaidFormat(w io.Writer, p *Plan) { +func WriteMermaidFormat(w io.Writer, p *physicalpb.Plan) { for _, root := range p.Roots() { node := BuildTree(p, root) printer := tree.NewMermaid(w) diff --git a/pkg/engine/internal/planner/physical/printer_test.go b/pkg/engine/internal/planner/physical/printer_test.go index 6eb2a730166fd..1a580afd85380 100644 --- a/pkg/engine/internal/planner/physical/printer_test.go +++ b/pkg/engine/internal/planner/physical/printer_test.go @@ -3,56 +3,70 @@ package physical import ( "testing" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" + "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid" ) func TestPrinter(t *testing.T) { t.Run("simple tree", func(t *testing.T) { - p := &Plan{} + p := &physicalpb.Plan{} + limitID := physicalpb.PlanNodeID{Value: ulid.New()} + filterID := physicalpb.PlanNodeID{Value: ulid.New()} + scanSetID := physicalpb.PlanNodeID{Value: ulid.New()} + limit := p.Add(&physicalpb.Limit{Id: limitID}) + filter := p.Add(&physicalpb.Filter{Id: filterID}) + scanSet := p.Add(&physicalpb.ScanSet{ + Id: scanSetID, - limit := p.graph.Add(&Limit{id: "limit"}) - filter := p.graph.Add(&Filter{id: "filter"}) - scanSet := p.graph.Add(&ScanSet{ - id: "set", - - Targets: []*ScanTarget{ - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, - {Type: ScanTypeDataObject, DataObject: &DataObjScan{}}, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{}}, }, }) - _ = p.graph.AddEdge(dag.Edge[Node]{Parent: limit, Child: filter}) - _ = p.graph.AddEdge(dag.Edge[Node]{Parent: filter, Child: scanSet}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(limit), Child: physicalpb.GetNode(filter)}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: physicalpb.GetNode(filter), Child: physicalpb.GetNode(scanSet)}) repr := PrintAsTree(p) t.Log("\n" + repr) }) t.Run("multiple root nodes", func(t *testing.T) { - p := &Plan{} + limit1ID := physicalpb.PlanNodeID{Value: ulid.New()} + limit2ID := physicalpb.PlanNodeID{Value: ulid.New()} + scan1ID := physicalpb.PlanNodeID{Value: ulid.New()} + scan2ID := physicalpb.PlanNodeID{Value: ulid.New()} + + p := &physicalpb.Plan{} - limit1 := p.graph.Add(&Limit{id: "limit1"}) - scan1 := p.graph.Add(&DataObjScan{id: "scan1"}) - _ = p.graph.AddEdge(dag.Edge[Node]{Parent: limit1, Child: scan1}) + limit1 := p.Add(&physicalpb.Limit{Id: limit1ID}) + scan1 := p.Add(&physicalpb.DataObjScan{Id: scan1ID}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: limit1.GetLimit(), Child: scan1.GetScan()}) - limit2 := p.graph.Add(&Limit{id: "limit2"}) - scan2 := p.graph.Add(&DataObjScan{id: "scan2"}) - _ = p.graph.AddEdge(dag.Edge[Node]{Parent: limit2, Child: scan2}) + limit2 := p.Add(&physicalpb.Limit{Id: limit2ID}) + scan2 := p.Add(&physicalpb.DataObjScan{Id: scan2ID}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: limit2.GetLimit(), Child: scan2.GetScan()}) repr := PrintAsTree(p) t.Log("\n" + repr) }) t.Run("multiple parents sharing the same child node", func(t *testing.T) { - p := &Plan{} - limit := p.graph.Add(&Limit{id: "limit"}) - filter1 := p.graph.Add(&Limit{id: "filter1"}) - filter2 := p.graph.Add(&Limit{id: "filter2"}) - scan := p.graph.Add(&DataObjScan{id: "scan"}) - _ = p.graph.AddEdge(dag.Edge[Node]{Parent: limit, Child: filter1}) - _ = p.graph.AddEdge(dag.Edge[Node]{Parent: limit, Child: filter2}) - _ = p.graph.AddEdge(dag.Edge[Node]{Parent: filter1, Child: scan}) - _ = p.graph.AddEdge(dag.Edge[Node]{Parent: filter2, Child: scan}) + limitID := physicalpb.PlanNodeID{Value: ulid.New()} + filter1ID := physicalpb.PlanNodeID{Value: ulid.New()} + filter2ID := physicalpb.PlanNodeID{Value: ulid.New()} + scanID := physicalpb.PlanNodeID{Value: ulid.New()} + + p := &physicalpb.Plan{} + limit := p.Add(&physicalpb.Limit{Id: limitID}) + filter1 := p.Add(&physicalpb.Limit{Id: filter1ID}) + filter2 := p.Add(&physicalpb.Limit{Id: filter2ID}) + scan := p.Add(&physicalpb.DataObjScan{Id: scanID}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: limit.GetLimit(), Child: filter1.GetFilter()}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: limit.GetLimit(), Child: filter2.GetFilter()}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter1.GetFilter(), Child: scan.GetScan()}) + _ = p.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter2.GetFilter(), Child: scan.GetScan()}) repr := PrintAsTree(p) t.Log("\n" + repr) diff --git a/pkg/engine/internal/planner/physical/projection.go b/pkg/engine/internal/planner/physical/projection.go deleted file mode 100644 index df9faa52e297f..0000000000000 --- a/pkg/engine/internal/planner/physical/projection.go +++ /dev/null @@ -1,51 +0,0 @@ -package physical - -import "fmt" - -// Projection represents a column selection operation in the physical plan. -// It contains a list of columns (column expressions) that are later -// evaluated against the input columns to remove unnecessary colums from the -// intermediate result. -type Projection struct { - id string - - // Expressions is a set of column expressions that are used to drop not needed - // columns that match the column expression, or to expand columns that result - // from the expressions. - Expressions []Expression - - All bool // Marker for projecting all columns of input relation (similar to SQL `SELECT *`) - Expand bool // Indicates that projected columns should be added to input relation - Drop bool // Indicates that projected columns should be dropped from input Relation -} - -// ID implements the [Node] interface. -// Returns a string that uniquely identifies the node in the plan. -func (p *Projection) ID() string { - if p.id == "" { - return fmt.Sprintf("%p", p) - } - return p.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (p *Projection) Clone() Node { - return &Projection{ - Expressions: cloneExpressions(p.Expressions), - All: p.All, - Expand: p.Expand, - Drop: p.Drop, - } -} - -// Type implements the [Node] interface. -// Returns the type of the node. -func (*Projection) Type() NodeType { - return NodeTypeProjection -} - -// Accept implements the [Node] interface. -// Dispatches itself to the provided [Visitor] v -func (p *Projection) Accept(v Visitor) error { - return v.VisitProjection(p) -} diff --git a/pkg/engine/internal/planner/physical/range_aggregate.go b/pkg/engine/internal/planner/physical/range_aggregate.go deleted file mode 100644 index 1196538f02f45..0000000000000 --- a/pkg/engine/internal/planner/physical/range_aggregate.go +++ /dev/null @@ -1,50 +0,0 @@ -package physical - -import ( - "fmt" - "time" - - "github.com/grafana/loki/v3/pkg/engine/internal/types" -) - -// TODO: Rename based on the actual implementation. -type RangeAggregation struct { - id string - - PartitionBy []ColumnExpression // Columns to partition the data by. - - Operation types.RangeAggregationType - Start time.Time - End time.Time - Step time.Duration // optional for instant queries - Range time.Duration -} - -func (r *RangeAggregation) ID() string { - if r.id == "" { - return fmt.Sprintf("%p", r) - } - - return r.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (r *RangeAggregation) Clone() Node { - return &RangeAggregation{ - PartitionBy: cloneExpressions(r.PartitionBy), - - Operation: r.Operation, - Start: r.Start, - End: r.End, - Step: r.Step, - Range: r.Range, - } -} - -func (r *RangeAggregation) Type() NodeType { - return NodeTypeRangeAggregation -} - -func (r *RangeAggregation) Accept(v Visitor) error { - return v.VisitRangeAggregation(r) -} diff --git a/pkg/engine/internal/planner/physical/scanset.go b/pkg/engine/internal/planner/physical/scanset.go deleted file mode 100644 index 52a95efde9d92..0000000000000 --- a/pkg/engine/internal/planner/physical/scanset.go +++ /dev/null @@ -1,115 +0,0 @@ -package physical - -import ( - "fmt" - "iter" -) - -// ScanTarget represents a target of a [ScanSet]. -type ScanTarget struct { - Type ScanType - - // DataObj is non-nil if Type is [ScanTypeDataObject]. Despite DataObjScan - // implementing [Node], the value is not inserted into the graph as a node. - DataObject *DataObjScan -} - -// Clone returns a copy of the scan target. -func (t *ScanTarget) Clone() *ScanTarget { - res := &ScanTarget{Type: t.Type} - if t.DataObject != nil { - res.DataObject = t.DataObject.Clone().(*DataObjScan) - } - return res -} - -// ScanType represents the data being scanned in a target of a [ScanSet]. -type ScanType int - -const ( - ScanTypeInvalid ScanType = iota - ScanTypeDataObject -) - -// String returns a string representation of the scan type. -func (ty ScanType) String() string { - switch ty { - case ScanTypeInvalid: - return "ScanTypeInvalid" - case ScanTypeDataObject: - return "ScanTypeDataObject" - default: - return fmt.Sprintf("ScanType(%d)", ty) - } -} - -// ScanSet represents a physical plan operation for reading data from targets. -type ScanSet struct { - id string - - // Targets to scan. - Targets []*ScanTarget - - // Projections are used to limit the columns that are read to the ones - // provided in the column expressions to reduce the amount of data that - // needs to be processed. - Projections []ColumnExpression - - // Predicates are used to filter rows to reduce the amount of rows that are - // returned. Predicates would almost always contain a time range filter to - // only read the logs for the requested time range. - Predicates []Expression -} - -// ID returns a string that uniquely identifies the node in the plan. -func (s *ScanSet) ID() string { - if s.id == "" { - return fmt.Sprintf("%p", s) - } - return s.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (s *ScanSet) Clone() Node { - newTargets := make([]*ScanTarget, 0, len(s.Targets)) - for _, target := range s.Targets { - newTargets = append(newTargets, target.Clone()) - } - - return &ScanSet{Targets: newTargets} -} - -// Type returns [NodeTypeScanSet]. -func (s *ScanSet) Type() NodeType { - return NodeTypeScanSet -} - -// Accept dispatches s to the provided [Visitor] v. -func (s *ScanSet) Accept(v Visitor) error { - return v.VisitScanSet(s) -} - -// Shards returns an iterator over the shards of the scan. Each emitted shard -// will be a clone. Projections and predicates on the ScanSet are cloned and -// applied to each shard. -// -// Shards panics if one of the targets is invalid. -func (s *ScanSet) Shards() iter.Seq[Node] { - return func(yield func(Node) bool) { - for _, target := range s.Targets { - switch target.Type { - case ScanTypeDataObject: - node := target.DataObject.Clone().(*DataObjScan) - node.Projections = cloneExpressions(s.Projections) - node.Predicates = cloneExpressions(s.Predicates) - - if !yield(node) { - return - } - - default: - panic(fmt.Sprintf("invalid scan type %s", target.Type)) - } - } - } -} diff --git a/pkg/engine/internal/planner/physical/topk.go b/pkg/engine/internal/planner/physical/topk.go deleted file mode 100644 index 60558d851e790..0000000000000 --- a/pkg/engine/internal/planner/physical/topk.go +++ /dev/null @@ -1,49 +0,0 @@ -package physical - -import ( - "fmt" -) - -// TopK represents a physical plan node that performs topK operation. -// It sorts rows based on sort expressions and limits the result to the top K rows. -// This is equivalent to a SORT followed by a LIMIT operation. -type TopK struct { - id string - - // SortBy is the column to sort by. - SortBy ColumnExpression - Ascending bool // Sort lines in ascending order if true. - NullsFirst bool // When true, considers NULLs < non-NULLs when sorting. - K int // Number of top rows to return. -} - -// ID implements the [Node] interface. -// Returns a string that uniquely identifies the node in the plan. -func (t *TopK) ID() string { - if t.id == "" { - return fmt.Sprintf("%p", t) - } - return t.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (t *TopK) Clone() Node { - return &TopK{ - SortBy: t.SortBy.Clone().(ColumnExpression), - Ascending: t.Ascending, - NullsFirst: t.NullsFirst, - K: t.K, - } -} - -// Type implements the [Node] interface. -// Returns the type of the node. -func (*TopK) Type() NodeType { - return NodeTypeTopK -} - -// Accept implements the [Node] interface. -// Dispatches itself to the provided [Visitor] v -func (t *TopK) Accept(visitor Visitor) error { - return visitor.VisitTopK(t) -} diff --git a/pkg/engine/internal/planner/physical/vector_aggregate.go b/pkg/engine/internal/planner/physical/vector_aggregate.go deleted file mode 100644 index b88c99d951256..0000000000000 --- a/pkg/engine/internal/planner/physical/vector_aggregate.go +++ /dev/null @@ -1,49 +0,0 @@ -package physical - -import ( - "fmt" - - "github.com/grafana/loki/v3/pkg/engine/internal/types" -) - -// VectorAggregation represents a physical plan node that performs vector aggregations. -// It computes aggregations over time series data at each timestamp instant, -// grouping results by specified dimensions. -type VectorAggregation struct { - id string - - // GroupBy defines the columns to group by. If empty, all rows are aggregated into a single result. - GroupBy []ColumnExpression - - // Operation defines the type of aggregation operation to perform (e.g., sum, min, max) - Operation types.VectorAggregationType -} - -// ID implements the [Node] interface. -// Returns a string that uniquely identifies the node in the plan. -func (v *VectorAggregation) ID() string { - if v.id == "" { - return fmt.Sprintf("%p", v) - } - return v.id -} - -// Clone returns a deep copy of the node (minus its ID). -func (v *VectorAggregation) Clone() Node { - return &VectorAggregation{ - GroupBy: cloneExpressions(v.GroupBy), - Operation: v.Operation, - } -} - -// Type implements the [Node] interface. -// Returns the type of the node. -func (*VectorAggregation) Type() NodeType { - return NodeTypeVectorAggregation -} - -// Accept implements the [Node] interface. -// Dispatches itself to the provided [Visitor] v -func (v *VectorAggregation) Accept(visitor Visitor) error { - return visitor.VisitVectorAggregation(v) -} diff --git a/pkg/engine/internal/planner/physical/visitor.go b/pkg/engine/internal/planner/physical/visitor.go deleted file mode 100644 index 8754be778d96a..0000000000000 --- a/pkg/engine/internal/planner/physical/visitor.go +++ /dev/null @@ -1,20 +0,0 @@ -package physical - -// Visitor defines the interface for objects that can visit each type of -// physical plan node. It implements the Visitor pattern, providing -// type-specific visit methods for each concrete node type in the physical -// plan. -type Visitor interface { - VisitDataObjScan(*DataObjScan) error - VisitProjection(*Projection) error - VisitRangeAggregation(*RangeAggregation) error - VisitFilter(*Filter) error - VisitLimit(*Limit) error - VisitVectorAggregation(*VectorAggregation) error - VisitParse(*ParseNode) error - VisitCompat(*ColumnCompat) error - VisitTopK(*TopK) error - VisitParallelize(*Parallelize) error - VisitScanSet(*ScanSet) error - VisitJoin(*Join) error -} diff --git a/pkg/engine/internal/planner/physical/visitor_test.go b/pkg/engine/internal/planner/physical/visitor_test.go index 4350125c7cdd0..06047d46f6181 100644 --- a/pkg/engine/internal/planner/physical/visitor_test.go +++ b/pkg/engine/internal/planner/physical/visitor_test.go @@ -2,114 +2,142 @@ package physical import ( "fmt" + + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" ) -var _ Visitor = (*nodeCollectVisitor)(nil) +var _ physicalpb.Visitor = (*nodeCollectVisitor)(nil) // A visitor implementation that collects nodes during traversal and optionally // executes custom functions for each node type. Used primarily for testing // traversal behavior. type nodeCollectVisitor struct { visited []string - onVisitDataObjScan func(*DataObjScan) error - onVisitFilter func(*Filter) error - onVisitLimit func(*Limit) error - onVisitProjection func(*Projection) error - onVisitRangeAggregation func(*RangeAggregation) error - onVisitVectorAggregation func(*VectorAggregation) error - onVisitParse func(*ParseNode) error - onVisitParallelize func(*Parallelize) error - onVisitScanSet func(*ScanSet) error - onVisitJoin func(*Join) error -} - -func (v *nodeCollectVisitor) VisitDataObjScan(n *DataObjScan) error { + onVisitDataObjScan func(*physicalpb.DataObjScan) error + onVisitFilter func(*physicalpb.Filter) error + onVisitLimit func(*physicalpb.Limit) error + onVisitProjection func(*physicalpb.Projection) error + onVisitRangeAggregation func(*physicalpb.AggregateRange) error + onVisitVectorAggregation func(*physicalpb.AggregateVector) error + onVisitParse func(*physicalpb.Parse) error + onVisitParallelize func(*physicalpb.Parallelize) error + onVisitScanSet func(*physicalpb.ScanSet) error + onVisitJoin func(*physicalpb.Join) error + onVisitColumnCompat func(*physicalpb.ColumnCompat) error + onVisitMerge func(*physicalpb.Merge) error + onVisitSortMerge func(*physicalpb.SortMerge) error +} + +func (v *nodeCollectVisitor) VisitDataObjScan(n *physicalpb.DataObjScan) error { if v.onVisitDataObjScan != nil { return v.onVisitDataObjScan(n) } - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } -func (v *nodeCollectVisitor) VisitFilter(n *Filter) error { +func (v *nodeCollectVisitor) VisitFilter(n *physicalpb.Filter) error { if v.onVisitFilter != nil { return v.onVisitFilter(n) } - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } -func (v *nodeCollectVisitor) VisitLimit(n *Limit) error { +func (v *nodeCollectVisitor) VisitLimit(n *physicalpb.Limit) error { if v.onVisitLimit != nil { return v.onVisitLimit(n) } - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } -func (v *nodeCollectVisitor) VisitProjection(n *Projection) error { +func (v *nodeCollectVisitor) VisitProjection(n *physicalpb.Projection) error { if v.onVisitProjection != nil { return v.onVisitProjection(n) } - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } -func (v *nodeCollectVisitor) VisitRangeAggregation(n *RangeAggregation) error { +func (v *nodeCollectVisitor) VisitAggregateRange(n *physicalpb.AggregateRange) error { if v.onVisitRangeAggregation != nil { return v.onVisitRangeAggregation(n) } - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } -func (v *nodeCollectVisitor) VisitVectorAggregation(n *VectorAggregation) error { +func (v *nodeCollectVisitor) VisitAggregateVector(n *physicalpb.AggregateVector) error { if v.onVisitVectorAggregation != nil { return v.onVisitVectorAggregation(n) } - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } -func (v *nodeCollectVisitor) VisitParse(n *ParseNode) error { +func (v *nodeCollectVisitor) VisitParse(n *physicalpb.Parse) error { if v.onVisitParse != nil { return v.onVisitParse(n) } - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } -func (v *nodeCollectVisitor) VisitCompat(*ColumnCompat) error { +func (v *nodeCollectVisitor) VisitCompat(*physicalpb.ColumnCompat) error { return nil } -func (v *nodeCollectVisitor) VisitTopK(n *TopK) error { - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) +func (v *nodeCollectVisitor) VisitTopK(n *physicalpb.TopK) error { + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } -func (v *nodeCollectVisitor) VisitParallelize(n *Parallelize) error { +func (v *nodeCollectVisitor) VisitParallelize(n *physicalpb.Parallelize) error { if v.onVisitParallelize != nil { return v.onVisitParallelize(n) } - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } -func (v *nodeCollectVisitor) VisitScanSet(n *ScanSet) error { +func (v *nodeCollectVisitor) VisitScanSet(n *physicalpb.ScanSet) error { if v.onVisitScanSet != nil { return v.onVisitScanSet(n) } - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) + return nil +} + +func (v *nodeCollectVisitor) VisitColumnCompat(n *physicalpb.ColumnCompat) error { + if v.onVisitColumnCompat != nil { + return v.onVisitColumnCompat(n) + } + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } -func (v *nodeCollectVisitor) VisitJoin(n *Join) error { +func (v *nodeCollectVisitor) VisitJoin(n *physicalpb.Join) error { if v.onVisitJoin != nil { return v.onVisitJoin(n) } - v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Type().String(), n.ID())) + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) + return nil +} + +func (v *nodeCollectVisitor) VisitMerge(n *physicalpb.Merge) error { + if v.onVisitMerge != nil { + return v.onVisitMerge(n) + } + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) + return nil +} +func (v *nodeCollectVisitor) VisitSortMerge(n *physicalpb.SortMerge) error { + if v.onVisitSortMerge != nil { + return v.onVisitSortMerge(n) + } + v.visited = append(v.visited, fmt.Sprintf("%s.%s", n.Kind().String(), n.ID())) return nil } diff --git a/pkg/engine/internal/planner/planner_test.go b/pkg/engine/internal/planner/planner_test.go index 54fa08e4ed180..5e62c90f38b1c 100644 --- a/pkg/engine/internal/planner/planner_test.go +++ b/pkg/engine/internal/planner/planner_test.go @@ -2,6 +2,7 @@ package planner import ( "context" + "fmt" "strings" "testing" "time" @@ -153,13 +154,13 @@ func TestFullQueryPlanning(t *testing.T) { query: `{app="foo"}`, expected: ` Limit offset=0 limit=1000 -└── TopK sort_by=builtin.timestamp ascending=false nulls_first=false k=1000 +└── TopK sort_by=&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,} ascending=false nulls_first=false k=1000 └── Parallelize - └── TopK sort_by=builtin.timestamp ascending=false nulls_first=false k=1000 - └── Compat src=metadata dst=metadata collision=label - └── ScanSet num_targets=2 predicate[0]=GTE(builtin.timestamp, 2025-01-01T00:00:00Z) predicate[1]=LT(builtin.timestamp, 2025-01-01T01:00:00Z) - ├── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() - └── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() + └── TopK sort_by=&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,} ascending=false nulls_first=false k=1000 + └── ColumnCompat src=COLUMN_TYPE_METADATA dst=COLUMN_TYPE_METADATA collision=COLUMN_TYPE_LABEL + └── ScanSet num_targets=2 predicate[0]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_GTE,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735689600000000000,},},},},},},},} predicate[1]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_LT,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735693200000000000,},},},},},},},} + ├── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() direction=SORT_ORDER_INVALID limit=0 + └── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 `, }, { @@ -167,14 +168,14 @@ Limit offset=0 limit=1000 query: `{app="foo"} | label_foo="bar" |= "baz"`, expected: ` Limit offset=0 limit=1000 -└── TopK sort_by=builtin.timestamp ascending=false nulls_first=false k=1000 +└── TopK sort_by=&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,} ascending=false nulls_first=false k=1000 └── Parallelize - └── TopK sort_by=builtin.timestamp ascending=false nulls_first=false k=1000 - └── Filter predicate[0]=EQ(ambiguous.label_foo, "bar") - └── Compat src=metadata dst=metadata collision=label - └── ScanSet num_targets=2 predicate[0]=GTE(builtin.timestamp, 2025-01-01T00:00:00Z) predicate[1]=LT(builtin.timestamp, 2025-01-01T01:00:00Z) predicate[2]=MATCH_STR(builtin.message, "baz") - ├── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() - └── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() + └── TopK sort_by=&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,} ascending=false nulls_first=false k=1000 + └── Filter predicate[0]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_EQ,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:label_foo,Type:COLUMN_TYPE_AMBIGUOUS,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_StringLiteral{StringLiteral:&StringLiteral{Value:bar,},},},},},},},} + └── ColumnCompat src=COLUMN_TYPE_METADATA dst=COLUMN_TYPE_METADATA collision=COLUMN_TYPE_LABEL + └── ScanSet num_targets=2 predicate[0]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_GTE,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735689600000000000,},},},},},},},} predicate[1]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_LT,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735693200000000000,},},},},},},},} predicate[2]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_MATCH_SUBSTR,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:message,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_StringLiteral{StringLiteral:&StringLiteral{Value:baz,},},},},},},},} + ├── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() direction=SORT_ORDER_INVALID limit=0 + └── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 `, }, { @@ -182,33 +183,16 @@ Limit offset=0 limit=1000 query: `{app="foo"} |= "bar" | logfmt | level="error"`, expected: ` Limit offset=0 limit=1000 -└── TopK sort_by=builtin.timestamp ascending=false nulls_first=false k=1000 +└── TopK sort_by=&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,} ascending=false nulls_first=false k=1000 └── Parallelize - └── TopK sort_by=builtin.timestamp ascending=false nulls_first=false k=1000 - └── Filter predicate[0]=EQ(ambiguous.level, "error") - └── Compat src=parsed dst=parsed collision=label - └── Parse kind=logfmt - └── Compat src=metadata dst=metadata collision=label - └── ScanSet num_targets=2 predicate[0]=GTE(builtin.timestamp, 2025-01-01T00:00:00Z) predicate[1]=LT(builtin.timestamp, 2025-01-01T01:00:00Z) predicate[2]=MATCH_STR(builtin.message, "bar") - ├── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() - └── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() - `, - }, - { - comment: "log: parse and drop columns", - query: `{app="foo"} | logfmt | drop service_name,__error__`, - expected: ` -Limit offset=0 limit=1000 -└── TopK sort_by=builtin.timestamp ascending=false nulls_first=false k=1000 - └── Parallelize - └── TopK sort_by=builtin.timestamp ascending=false nulls_first=false k=1000 - └── Projection all=true drop=(ambiguous.service_name, ambiguous.__error__) - └── Compat src=parsed dst=parsed collision=label - └── Parse kind=logfmt - └── Compat src=metadata dst=metadata collision=label - └── ScanSet num_targets=2 predicate[0]=GTE(builtin.timestamp, 2025-01-01T00:00:00Z) predicate[1]=LT(builtin.timestamp, 2025-01-01T01:00:00Z) - ├── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() - └── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() + └── TopK sort_by=&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,} ascending=false nulls_first=false k=1000 + └── Filter predicate[0]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_EQ,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:level,Type:COLUMN_TYPE_AMBIGUOUS,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_StringLiteral{StringLiteral:&StringLiteral{Value:error,},},},},},},},} + └── ColumnCompat src=COLUMN_TYPE_PARSED dst=COLUMN_TYPE_PARSED collision=COLUMN_TYPE_LABEL + └── Parse kind=PARSE_OP_LOGFMT + └── ColumnCompat src=COLUMN_TYPE_METADATA dst=COLUMN_TYPE_METADATA collision=COLUMN_TYPE_LABEL + └── ScanSet num_targets=2 predicate[0]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_GTE,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735689600000000000,},},},},},},},} predicate[1]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_LT,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735693200000000000,},},},},},},},} predicate[2]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_MATCH_SUBSTR,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:message,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_StringLiteral{StringLiteral:&StringLiteral{Value:bar,},},},},},},},} + ├── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() direction=SORT_ORDER_INVALID limit=0 + └── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 `, }, { @@ -219,51 +203,50 @@ Limit offset=0 limit=1000 comment: "metric: parse, unwrap and aggregate", query: `sum by (bar) (sum_over_time({app="foo"} | logfmt | request_duration != "" | unwrap duration(request_duration)[1m]))`, expected: ` -VectorAggregation operation=sum group_by=(ambiguous.bar) -└── RangeAggregation operation=sum start=2025-01-01T00:00:00Z end=2025-01-01T01:00:00Z step=0s range=1m0s partition_by=(ambiguous.bar) +AggregateVector operation=AGGREGATE_VECTOR_OP_SUM group_by=(&ColumnExpression{Name:bar,Type:COLUMN_TYPE_AMBIGUOUS,}) +└── AggregateRange operation=AGGREGATE_RANGE_OP_SUM start=2025-01-01T00:00:00Z end=2025-01-01T01:00:00Z step=0s range=1m0s partition_by=(&ColumnExpression{Name:bar,Type:COLUMN_TYPE_AMBIGUOUS,}) └── Parallelize - └── Projection all=true expand=(CAST_DURATION(ambiguous.request_duration)) - └── Filter predicate[0]=NEQ(ambiguous.request_duration, "") - └── Compat src=parsed dst=parsed collision=label - └── Parse kind=logfmt requested_keys=(bar, request_duration) - └── Compat src=metadata dst=metadata collision=label - └── ScanSet num_targets=2 projections=(ambiguous.bar, builtin.message, ambiguous.request_duration, builtin.timestamp) predicate[0]=GTE(builtin.timestamp, 2024-12-31T23:59:00Z) predicate[1]=LT(builtin.timestamp, 2025-01-01T01:00:00Z) - ├── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() - └── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() + └── Projection all=true expand=(&Expression{Kind:&Expression_UnaryExpression{UnaryExpression:&UnaryExpression{Op:UNARY_OP_CAST_DURATION,Value:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:request_duration,Type:COLUMN_TYPE_AMBIGUOUS,},},},},},}) + └── Filter predicate[0]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_NEQ,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:request_duration,Type:COLUMN_TYPE_AMBIGUOUS,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_StringLiteral{StringLiteral:&StringLiteral{Value:,},},},},},},},} + └── ColumnCompat src=COLUMN_TYPE_PARSED dst=COLUMN_TYPE_PARSED collision=COLUMN_TYPE_LABEL + └── Parse kind=PARSE_OP_LOGFMT requested_keys=(bar, request_duration) + └── ColumnCompat src=COLUMN_TYPE_METADATA dst=COLUMN_TYPE_METADATA collision=COLUMN_TYPE_LABEL + └── ScanSet num_targets=2 projections=(&ColumnExpression{Name:bar,Type:COLUMN_TYPE_AMBIGUOUS,}, &ColumnExpression{Name:message,Type:COLUMN_TYPE_BUILTIN,}, &ColumnExpression{Name:request_duration,Type:COLUMN_TYPE_AMBIGUOUS,}, &ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,}) predicate[0]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_GTE,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735689540000000000,},},},},},},},} predicate[1]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_LT,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735693200000000000,},},},},},},},} + ├── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() direction=SORT_ORDER_INVALID limit=0 + └── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 `, }, { comment: `metric: multiple parse stages`, query: `sum(count_over_time({app="foo"} | detected_level="error" | json | logfmt | drop __error__,__error_details__[1m]))`, expected: ` -VectorAggregation operation=sum -└── RangeAggregation operation=count start=2025-01-01T00:00:00Z end=2025-01-01T01:00:00Z step=0s range=1m0s +AggregateVector operation=AGGREGATE_VECTOR_OP_SUM +└── AggregateRange operation=AGGREGATE_RANGE_OP_COUNT start=2025-01-01T00:00:00Z end=2025-01-01T01:00:00Z step=0s range=1m0s └── Parallelize - └── Projection all=true drop=(ambiguous.__error__, ambiguous.__error_details__) - └── Compat src=parsed dst=parsed collision=label - └── Parse kind=json - └── Compat src=parsed dst=parsed collision=label - └── Parse kind=logfmt - └── Filter predicate[0]=EQ(ambiguous.detected_level, "error") - └── Compat src=metadata dst=metadata collision=label - └── ScanSet num_targets=2 projections=(ambiguous.detected_level, builtin.message, builtin.timestamp) predicate[0]=GTE(builtin.timestamp, 2024-12-31T23:59:00Z) predicate[1]=LT(builtin.timestamp, 2025-01-01T01:00:00Z) - ├── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() - └── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() - + └── Projection all=true drop=(&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:__error__,Type:COLUMN_TYPE_AMBIGUOUS,},},}, &Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:__error_details__,Type:COLUMN_TYPE_AMBIGUOUS,},},}) + └── ColumnCompat src=COLUMN_TYPE_PARSED dst=COLUMN_TYPE_PARSED collision=COLUMN_TYPE_LABEL + └── Parse kind=PARSE_OP_JSON + └── ColumnCompat src=COLUMN_TYPE_PARSED dst=COLUMN_TYPE_PARSED collision=COLUMN_TYPE_LABEL + └── Parse kind=PARSE_OP_LOGFMT + └── Filter predicate[0]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_EQ,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:detected_level,Type:COLUMN_TYPE_AMBIGUOUS,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_StringLiteral{StringLiteral:&StringLiteral{Value:error,},},},},},},},} + └── ColumnCompat src=COLUMN_TYPE_METADATA dst=COLUMN_TYPE_METADATA collision=COLUMN_TYPE_LABEL + └── ScanSet num_targets=2 projections=(&ColumnExpression{Name:detected_level,Type:COLUMN_TYPE_AMBIGUOUS,}, &ColumnExpression{Name:message,Type:COLUMN_TYPE_BUILTIN,}, &ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,}) predicate[0]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_GTE,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735689540000000000,},},},},},},},} predicate[1]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_LT,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735693200000000000,},},},},},},},} + ├── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() direction=SORT_ORDER_INVALID limit=0 + └── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 `, }, { comment: "math expression", query: `sum by (bar) (count_over_time({app="foo"}[1m]) / 300)`, expected: ` -VectorAggregation operation=sum group_by=(ambiguous.bar) -└── Projection all=true expand=(DIV(generated.value, 300)) - └── RangeAggregation operation=count start=2025-01-01T00:00:00Z end=2025-01-01T01:00:00Z step=0s range=1m0s partition_by=(ambiguous.bar) +AggregateVector operation=AGGREGATE_VECTOR_OP_SUM group_by=(&ColumnExpression{Name:bar,Type:COLUMN_TYPE_AMBIGUOUS,}) +└── Projection all=true expand=(&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_DIV,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:value,Type:COLUMN_TYPE_GENERATED,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_FloatLiteral{FloatLiteral:&FloatLiteral{Value:300,},},},},},},},}) + └── AggregateRange operation=AGGREGATE_RANGE_OP_COUNT start=2025-01-01T00:00:00Z end=2025-01-01T01:00:00Z step=0s range=1m0s partition_by=(&ColumnExpression{Name:bar,Type:COLUMN_TYPE_AMBIGUOUS,}) └── Parallelize - └── Compat src=metadata dst=metadata collision=label - └── ScanSet num_targets=2 projections=(ambiguous.bar, builtin.timestamp) predicate[0]=GTE(builtin.timestamp, 2024-12-31T23:59:00Z) predicate[1]=LT(builtin.timestamp, 2025-01-01T01:00:00Z) - ├── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() - └── @target type=ScanTypeDataObject location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() + └── ColumnCompat src=COLUMN_TYPE_METADATA dst=COLUMN_TYPE_METADATA collision=COLUMN_TYPE_LABEL + └── ScanSet num_targets=2 projections=(&ColumnExpression{Name:bar,Type:COLUMN_TYPE_AMBIGUOUS,}, &ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,}) predicate[0]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_GTE,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735689540000000000,},},},},},},},} predicate[1]=&Expression{Kind:&Expression_BinaryExpression{BinaryExpression:&BinaryExpression{Op:BINARY_OP_LT,Left:&Expression{Kind:&Expression_ColumnExpression{ColumnExpression:&ColumnExpression{Name:timestamp,Type:COLUMN_TYPE_BUILTIN,},},},Right:&Expression{Kind:&Expression_LiteralExpression{LiteralExpression:&LiteralExpression{Kind:&LiteralExpression_TimestampLiteral{TimestampLiteral:&TimestampLiteral{Value:1735693200000000000,},},},},},},},} + ├── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=1 projections=() direction=SORT_ORDER_INVALID limit=0 + └── @target type=SCAN_TYPE_DATA_OBJECT location=objects/00/0000000000.dataobj streams=5 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 `, }, } @@ -282,6 +265,7 @@ VectorAggregation operation=sum group_by=(ambiguous.bar) direction: logproto.BACKWARD, } + fmt.Println(tc.query) logicalPlan, err := logical.BuildPlan(q) require.NoError(t, err) @@ -289,11 +273,17 @@ VectorAggregation operation=sum group_by=(ambiguous.bar) planner := physical.NewPlanner(physical.NewContext(q.Start(), q.End()), catalog) plan, err := planner.Build(logicalPlan) + //tmp := physical.PrintAsTree(plan) + //fmt.Println(tmp) + require.NoError(t, err) plan, err = planner.Optimize(plan) require.NoError(t, err) actual := physical.PrintAsTree(plan) + if tc.comment == `metric: multiple parse stages` { + t.Logf("first failing test case") + } require.Equal(t, strings.TrimSpace(tc.expected), strings.TrimSpace(actual)) }) } diff --git a/pkg/engine/internal/scheduler/scheduler_test.go b/pkg/engine/internal/scheduler/scheduler_test.go index 484f3b21f2393..e02ce274fc54d 100644 --- a/pkg/engine/internal/scheduler/scheduler_test.go +++ b/pkg/engine/internal/scheduler/scheduler_test.go @@ -14,7 +14,7 @@ import ( "go.uber.org/atomic" "github.com/grafana/loki/v3/pkg/engine/internal/executor" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/scheduler/wire" "github.com/grafana/loki/v3/pkg/engine/internal/workflow" ) @@ -79,7 +79,7 @@ func TestScheduler_RemoveStreams(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sources: map[physical.Node][]*workflow.Stream{ + Sources: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -87,7 +87,7 @@ func TestScheduler_RemoveStreams(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -111,7 +111,7 @@ func TestScheduler_RemoveStreams(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -169,7 +169,7 @@ func TestScheduler_Listen(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sources: map[physical.Node][]*workflow.Stream{ + Sources: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -277,7 +277,7 @@ func TestScheduler_Listen(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -302,7 +302,7 @@ func TestScheduler_Start(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sources: map[physical.Node][]*workflow.Stream{ + Sources: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -310,7 +310,7 @@ func TestScheduler_Start(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -332,7 +332,7 @@ func TestScheduler_Start(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -340,7 +340,7 @@ func TestScheduler_Start(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -361,7 +361,7 @@ func TestScheduler_Start(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sources: map[physical.Node][]*workflow.Stream{ + Sources: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -369,7 +369,7 @@ func TestScheduler_Start(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sources: map[physical.Node][]*workflow.Stream{ + Sources: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -390,7 +390,7 @@ func TestScheduler_Start(t *testing.T) { ULID: ulid.Make(), Fragment: nil, - Sources: map[physical.Node][]*workflow.Stream{ + Sources: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -635,7 +635,7 @@ func TestScheduler_worker(t *testing.T) { task = workflow.Task{ ULID: ulid.Make(), - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -699,7 +699,7 @@ func TestScheduler_worker(t *testing.T) { task = workflow.Task{ ULID: ulid.Make(), - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -776,7 +776,7 @@ func TestScheduler_worker(t *testing.T) { receiver = workflow.Task{ ULID: ulid.Make(), - Sources: map[physical.Node][]*workflow.Stream{ + Sources: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -784,7 +784,7 @@ func TestScheduler_worker(t *testing.T) { sender = workflow.Task{ ULID: ulid.Make(), - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -851,7 +851,7 @@ func TestScheduler_worker(t *testing.T) { receiver = workflow.Task{ ULID: ulid.Make(), - Sources: map[physical.Node][]*workflow.Stream{ + Sources: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -859,7 +859,7 @@ func TestScheduler_worker(t *testing.T) { sender = workflow.Task{ ULID: ulid.Make(), - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -991,7 +991,7 @@ func TestScheduler_worker(t *testing.T) { task = workflow.Task{ ULID: ulid.Make(), - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -1056,14 +1056,14 @@ func TestScheduler_worker(t *testing.T) { receiver = workflow.Task{ ULID: ulid.Make(), - Sources: map[physical.Node][]*workflow.Stream{ + Sources: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } sender = workflow.Task{ ULID: ulid.Make(), - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -1145,7 +1145,7 @@ func TestScheduler_worker(t *testing.T) { sender = workflow.Task{ ULID: ulid.Make(), - Sinks: map[physical.Node][]*workflow.Stream{ + Sinks: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } @@ -1194,7 +1194,7 @@ func TestScheduler_worker(t *testing.T) { receiver = workflow.Task{ ULID: ulid.Make(), - Sources: map[physical.Node][]*workflow.Stream{ + Sources: map[physicalpb.Node][]*workflow.Stream{ nil: {&stream}, }, } diff --git a/pkg/engine/internal/semconv/identifier.go b/pkg/engine/internal/semconv/identifier.go index 357dc7d096fa5..41224ab842688 100644 --- a/pkg/engine/internal/semconv/identifier.go +++ b/pkg/engine/internal/semconv/identifier.go @@ -5,6 +5,8 @@ import ( "fmt" "strings" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) @@ -13,19 +15,38 @@ const ( ) var ( - ColumnIdentMessage = NewIdentifier("message", types.ColumnTypeBuiltin, types.Loki.String) - ColumnIdentTimestamp = NewIdentifier("timestamp", types.ColumnTypeBuiltin, types.Loki.Timestamp) - ColumnIdentValue = NewIdentifier("value", types.ColumnTypeGenerated, types.Loki.Float) - ColumnIdentError = NewIdentifier("__error__", types.ColumnTypeGenerated, types.Loki.String) - ColumnIdentErrorDetails = NewIdentifier("__error_details__", types.ColumnTypeGenerated, types.Loki.String) + ColumnIdentMessage = NewIdentifier("message", physicalpb.COLUMN_TYPE_BUILTIN, types.Loki.String) + ColumnIdentTimestamp = NewIdentifier("timestamp", physicalpb.COLUMN_TYPE_BUILTIN, types.Loki.Timestamp) + ColumnIdentValue = NewIdentifier("value", physicalpb.COLUMN_TYPE_GENERATED, types.Loki.Float) + ColumnIdentError = NewIdentifier("__error__", physicalpb.COLUMN_TYPE_GENERATED, types.Loki.String) + ColumnIdentErrorDetails = NewIdentifier("__error_details__", physicalpb.COLUMN_TYPE_GENERATED, types.Loki.String) ) +func ColumnTypePhysToLog(colType physicalpb.ColumnType) types.ColumnType { + switch colType { + case physicalpb.COLUMN_TYPE_BUILTIN: + return types.ColumnTypeBuiltin + case physicalpb.COLUMN_TYPE_LABEL: + return types.ColumnTypeLabel + case physicalpb.COLUMN_TYPE_METADATA: + return types.ColumnTypeMetadata + case physicalpb.COLUMN_TYPE_PARSED: + return types.ColumnTypeParsed + case physicalpb.COLUMN_TYPE_AMBIGUOUS: + return types.ColumnTypeAmbiguous + case physicalpb.COLUMN_TYPE_GENERATED: + return types.ColumnTypeGenerated + default: + return types.ColumnTypeInvalid + } +} + // NewIdentifier creates a new column identifier from given name, column type, and data type. // The semantic type of an identifier is derived from its column type. -func NewIdentifier(name string, ct types.ColumnType, dt types.DataType) *Identifier { +func NewIdentifier(name string, ct physicalpb.ColumnType, dt types.DataType) *Identifier { return &Identifier{ columnName: name, - columnType: ct, + columnType: ColumnTypePhysToLog(ct), dataType: dt, } } @@ -52,6 +73,11 @@ func (i *Identifier) ColumnType() types.ColumnType { return i.columnType } +// ColumnTypePhys returns the column type of the identifier as a physicalpb.ColumnType. +func (i *Identifier) ColumnTypePhys() physicalpb.ColumnType { + return physical.ColumnTypeLogToPhys(i.columnType) +} + // SemType returns the semantic type of the identifier. func (i *Identifier) SemType() SemanticType { return SemTypeForColumnType(i.columnType) @@ -102,7 +128,7 @@ func (i *Identifier) Equal(other *Identifier) bool { } // FQN returns a fully qualified name for a column by given name, column type, and data type. -func FQN(name string, ct types.ColumnType, dt types.DataType) string { +func FQN(name string, ct physicalpb.ColumnType, dt types.DataType) string { return NewIdentifier(name, ct, dt).FQN() } @@ -185,7 +211,7 @@ const ( InvalidType = semType("") ) -// SemTypeForColumnType converts a given [types.ColumnType] into a [SemanticType]. +// SemTypeForColumnType converts a given [physicalpb.ColumnType] into a [SemanticType]. func SemTypeForColumnType(value types.ColumnType) SemanticType { switch value { case types.ColumnTypeLabel: diff --git a/pkg/engine/internal/semconv/identifier_test.go b/pkg/engine/internal/semconv/identifier_test.go index 93659dd0f7537..40ddc86700307 100644 --- a/pkg/engine/internal/semconv/identifier_test.go +++ b/pkg/engine/internal/semconv/identifier_test.go @@ -6,28 +6,29 @@ import ( "github.com/stretchr/testify/require" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/types" ) func TestFullyQualifiedName(t *testing.T) { tc := []struct { name string - columnType types.ColumnType + columnType physicalpb.ColumnType dataType types.DataType expected string }{ // Resource scope - {"service_name", types.ColumnTypeLabel, types.Loki.String, "utf8.label.service_name"}, - {"service.name", types.ColumnTypeLabel, types.Loki.String, "utf8.label.service.name"}, + {"service_name", physicalpb.COLUMN_TYPE_LABEL, types.Loki.String, "utf8.label.service_name"}, + {"service.name", physicalpb.COLUMN_TYPE_LABEL, types.Loki.String, "utf8.label.service.name"}, // Record scope - {"message", types.ColumnTypeBuiltin, types.Loki.String, "utf8.builtin.message"}, - {"timestamp", types.ColumnTypeBuiltin, types.Loki.Timestamp, "timestamp_ns.builtin.timestamp"}, - {"trace_id", types.ColumnTypeMetadata, types.Loki.String, "utf8.metadata.trace_id"}, + {"message", physicalpb.COLUMN_TYPE_BUILTIN, types.Loki.String, "utf8.builtin.message"}, + {"timestamp", physicalpb.COLUMN_TYPE_BUILTIN, types.Loki.Timestamp, "timestamp_ns.builtin.timestamp"}, + {"trace_id", physicalpb.COLUMN_TYPE_METADATA, types.Loki.String, "utf8.metadata.trace_id"}, // Generated scope - {"value", types.ColumnTypeGenerated, types.Loki.Float, "float64.generated.value"}, - {"caller", types.ColumnTypeParsed, types.Loki.String, "utf8.parsed.caller"}, + {"value", physicalpb.COLUMN_TYPE_GENERATED, types.Loki.Float, "float64.generated.value"}, + {"caller", physicalpb.COLUMN_TYPE_PARSED, types.Loki.String, "utf8.parsed.caller"}, // Unscoped - {"service.name", types.ColumnTypeAmbiguous, types.Loki.String, "utf8.ambiguous.service.name"}, + {"service.name", physicalpb.COLUMN_TYPE_AMBIGUOUS, types.Loki.String, "utf8.ambiguous.service.name"}, } for _, tt := range tc { diff --git a/pkg/engine/internal/types/literal.go b/pkg/engine/internal/types/literal.go index ed6029334f9eb..0f69c121a9a94 100644 --- a/pkg/engine/internal/types/literal.go +++ b/pkg/engine/internal/types/literal.go @@ -7,6 +7,7 @@ import ( "github.com/dustin/go-humanize" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/util" ) @@ -214,22 +215,60 @@ var ( _ TypedLiteral[Bytes] = (*BytesLiteral)(nil) ) +func NewLiteralFromKind(value physicalpb.LiteralExpression) Literal { + switch kind := value.Kind.(type) { + case *physicalpb.LiteralExpression_BoolLiteral: + return BoolLiteral(kind.BoolLiteral.Value) + case *physicalpb.LiteralExpression_StringLiteral: + return StringLiteral(kind.StringLiteral.Value) + case *physicalpb.LiteralExpression_IntegerLiteral: + return IntegerLiteral(kind.IntegerLiteral.Value) + case *physicalpb.LiteralExpression_FloatLiteral: + return FloatLiteral(kind.FloatLiteral.Value) + case *physicalpb.LiteralExpression_TimestampLiteral: + return TimestampLiteral(kind.TimestampLiteral.Value) + case *physicalpb.LiteralExpression_DurationLiteral: + return DurationLiteral(kind.DurationLiteral.Value) + case *physicalpb.LiteralExpression_BytesLiteral: + return BytesLiteral(kind.BytesLiteral.Value) + } + panic(fmt.Sprintf("invalid literal value type %T", value.Kind)) +} + func NewLiteral[T LiteralType](value T) Literal { switch val := any(value).(type) { + case *physicalpb.LiteralExpression_BoolLiteral: + return BoolLiteral(val.BoolLiteral.Value) case bool: return BoolLiteral(val) + case *physicalpb.LiteralExpression_StringLiteral: + return StringLiteral(val.StringLiteral.Value) case string: return StringLiteral(val) + case *physicalpb.LiteralExpression_IntegerLiteral: + return IntegerLiteral(val.IntegerLiteral.Value) case int64: return IntegerLiteral(val) + case *physicalpb.LiteralExpression_FloatLiteral: + return FloatLiteral(val.FloatLiteral.Value) case float64: return FloatLiteral(val) + case *physicalpb.LiteralExpression_TimestampLiteral: + return TimestampLiteral(val.TimestampLiteral.Value) case Timestamp: return TimestampLiteral(val) + case *physicalpb.LiteralExpression_DurationLiteral: + return DurationLiteral(val.DurationLiteral.Value) case Duration: return DurationLiteral(val) + case *physicalpb.LiteralExpression_BytesLiteral: + return BytesLiteral(val.BytesLiteral.Value) case Bytes: return BytesLiteral(val) + case *physicalpb.LiteralExpression_NullLiteral: + return NewNullLiteral() + case nil: + return NewNullLiteral() } panic(fmt.Sprintf("invalid literal value type %T", value)) } diff --git a/pkg/engine/internal/util/ulid/ulid.go b/pkg/engine/internal/util/ulid/ulid.go new file mode 100644 index 0000000000000..05e18d267f0d3 --- /dev/null +++ b/pkg/engine/internal/util/ulid/ulid.go @@ -0,0 +1,144 @@ +// Package ulid provides a ULID implementation. It wraps around the + +// github.com/oklog/ulid/v2 package but supports being used as a custom type in + +// a gogoproto generated struct. + +package ulid + +import ( + "encoding/json" + + "github.com/oklog/ulid/v2" +) + +// A ULID is a 16-byte Universally Unique Lexicographically Sortable Identifier. + +type ULID ulid.ULID + +// New returns a new ULID. + +func New() ULID { return ULID(ulid.Make()) } + +// NewFromBytes returns a new ULID from the given byte array. Used for testing only. +func NewFromULID(ulid ulid.ULID) ULID { + return ULID(ulid) +} + +// Marshal marshals id as a [ProtoULID]. + +func (id ULID) Marshal() ([]byte, error) { + + pb := ProtoULID{Value: id[:]} + + return pb.Marshal() + +} + +// MarshalTo marshals id as a [ProtoULID] to the given data slice. The data + +// buffer must be at least [ULID.Size] bytes, otherwise MarshalTo panics. + +func (id *ULID) MarshalTo(data []byte) (int, error) { + + pb := ProtoULID{Value: id[:]} + + return pb.MarshalTo(data) + +} + +// Unmarshal unmarshals a [ProtoULID] from the given data slice. + +func (id *ULID) Unmarshal(data []byte) error { + + pb := ProtoULID{} + + if err := pb.Unmarshal(data); err != nil { + + return err + + } + + var inner ulid.ULID + + if err := inner.UnmarshalBinary(pb.GetValue()); err != nil { + + return err + + } + + *id = ULID(inner) + + return nil + +} + +// Size returns the size of the ULID when marshaled as a [ProtoULID]. + +func (id *ULID) Size() int { + + pb := ProtoULID{Value: id[:]} + + return pb.Size() + +} + +// MarshalJSON marshals the ULID to a JSON string. + +func (id ULID) MarshalJSON() ([]byte, error) { + + text, _ := ulid.ULID(id).MarshalText() + + return json.Marshal(string(text)) + +} + +// UnmarshalJSON unmarshals a JSON string into a ULID. + +func (id *ULID) UnmarshalJSON(data []byte) error { + + var text string + + if err := json.Unmarshal(data, &text); err != nil { + + return err + + } + + var inner ulid.ULID + + if err := inner.UnmarshalText([]byte(text)); err != nil { + + return err + + } + + *id = ULID(inner) + + return nil + +} + +// Compare compares the id to another ULID. + +func (id ULID) Compare(other ULID) int { + + return ulid.ULID(id).Compare(ulid.ULID(other)) + +} + +// Equal returns true if the id is equal to another ULID. + +func (id ULID) Equal(other ULID) bool { + + return id.Compare(other) == 0 + +} + +// String returns the ULID as a string. + +func (id ULID) String() string { + + return ulid.ULID(id).String() + +} diff --git a/pkg/engine/internal/util/ulid/ulid.pb.go b/pkg/engine/internal/util/ulid/ulid.pb.go new file mode 100644 index 0000000000000..013d061f3cadb --- /dev/null +++ b/pkg/engine/internal/util/ulid/ulid.pb.go @@ -0,0 +1,412 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pkg/engine/internal/util/ulid/ulid.proto + +package ulid + +import ( + bytes "bytes" + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" + reflect "reflect" + strings "strings" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type ProtoULID struct { + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *ProtoULID) Reset() { *m = ProtoULID{} } +func (*ProtoULID) ProtoMessage() {} +func (*ProtoULID) Descriptor() ([]byte, []int) { + return fileDescriptor_0061f2625f299e1f, []int{0} +} +func (m *ProtoULID) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ProtoULID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ProtoULID.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ProtoULID) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProtoULID.Merge(m, src) +} +func (m *ProtoULID) XXX_Size() int { + return m.Size() +} +func (m *ProtoULID) XXX_DiscardUnknown() { + xxx_messageInfo_ProtoULID.DiscardUnknown(m) +} + +var xxx_messageInfo_ProtoULID proto.InternalMessageInfo + +func (m *ProtoULID) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func init() { + proto.RegisterType((*ProtoULID)(nil), "ulid.loki.v1.ProtoULID") +} + +func init() { + proto.RegisterFile("pkg/engine/internal/util/ulid/ulid.proto", fileDescriptor_0061f2625f299e1f) +} + +var fileDescriptor_0061f2625f299e1f = []byte{ + // 194 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x28, 0xc8, 0x4e, 0xd7, + 0x4f, 0xcd, 0x4b, 0xcf, 0xcc, 0x4b, 0xd5, 0xcf, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, + 0x2f, 0x2d, 0xc9, 0xcc, 0xd1, 0x2f, 0xcd, 0xc9, 0x4c, 0x01, 0x13, 0x7a, 0x05, 0x45, 0xf9, 0x25, + 0xf9, 0x42, 0x3c, 0x60, 0x76, 0x4e, 0x7e, 0x76, 0xa6, 0x5e, 0x99, 0xa1, 0x92, 0x22, 0x17, 0x67, + 0x00, 0x48, 0x38, 0xd4, 0xc7, 0xd3, 0x45, 0x48, 0x84, 0x8b, 0xb5, 0x2c, 0x31, 0xa7, 0x34, 0x55, + 0x82, 0x51, 0x81, 0x51, 0x83, 0x27, 0x08, 0xc2, 0x71, 0xca, 0xbb, 0xf0, 0x50, 0x8e, 0xe1, 0xc6, + 0x43, 0x39, 0x86, 0x0f, 0x0f, 0xe5, 0x18, 0x1b, 0x1e, 0xc9, 0x31, 0xae, 0x78, 0x24, 0xc7, 0x78, + 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0xbe, 0x78, 0x24, 0xc7, + 0xf0, 0xe1, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, + 0xc7, 0x10, 0x65, 0x91, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x9f, 0x5e, + 0x94, 0x98, 0x96, 0x98, 0x97, 0xa8, 0x0f, 0xb2, 0x54, 0xbf, 0xcc, 0x58, 0x1f, 0xaf, 0x5b, 0x93, + 0xd8, 0xc0, 0xee, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x93, 0x61, 0x2c, 0x85, 0xd3, 0x00, + 0x00, 0x00, +} + +func (this *ProtoULID) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ProtoULID) + if !ok { + that2, ok := that.(ProtoULID) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Value, that1.Value) { + return false + } + return true +} +func (this *ProtoULID) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&ulid.ProtoULID{") + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func valueToGoStringUlid(v interface{}, typ string) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) +} +func (m *ProtoULID) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ProtoULID) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ProtoULID) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Value) > 0 { + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarintUlid(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintUlid(dAtA []byte, offset int, v uint64) int { + offset -= sovUlid(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ProtoULID) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Value) + if l > 0 { + n += 1 + l + sovUlid(uint64(l)) + } + return n +} + +func sovUlid(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozUlid(x uint64) (n int) { + return sovUlid(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *ProtoULID) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ProtoULID{`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} +func valueToStringUlid(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *ProtoULID) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUlid + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ProtoULID: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ProtoULID: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUlid + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthUlid + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthUlid + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...) + if m.Value == nil { + m.Value = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipUlid(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthUlid + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthUlid + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipUlid(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowUlid + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowUlid + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowUlid + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthUlid + } + iNdEx += length + if iNdEx < 0 { + return 0, ErrInvalidLengthUlid + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowUlid + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipUlid(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + if iNdEx < 0 { + return 0, ErrInvalidLengthUlid + } + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthUlid = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowUlid = fmt.Errorf("proto: integer overflow") +) diff --git a/pkg/engine/internal/util/ulid/ulid.proto b/pkg/engine/internal/util/ulid/ulid.proto new file mode 100644 index 0000000000000..72821d35f59eb --- /dev/null +++ b/pkg/engine/internal/util/ulid/ulid.proto @@ -0,0 +1,21 @@ +// ulid.proto holds a ULID type. + +syntax = "proto3"; + +package ulid.loki.v1; + +option go_package = "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid"; + +// ProtoULID represents a Universally Unique Lexicographically Sortable + +// Identifier (ULID) over protobuf. + +message ProtoULID { + // Value holds the [binary representation] of the ULID. + + // + + // [binary representation]: https://github.com/ulid/spec?tab=readme-ov-file#binary-layout-and-byte-order + + bytes value = 1; +} diff --git a/pkg/engine/internal/worker/thread.go b/pkg/engine/internal/worker/thread.go index b0bdadc47d10e..d1f2dbc3fe98d 100644 --- a/pkg/engine/internal/worker/thread.go +++ b/pkg/engine/internal/worker/thread.go @@ -13,7 +13,7 @@ import ( "github.com/thanos-io/objstore" "github.com/grafana/loki/v3/pkg/engine/internal/executor" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/scheduler/wire" "github.com/grafana/loki/v3/pkg/engine/internal/workflow" "github.com/grafana/loki/v3/pkg/logqlmodel/stats" @@ -111,7 +111,7 @@ func (t *thread) runJob(ctx context.Context, job *threadJob) { BatchSize: t.BatchSize, Bucket: t.Bucket, - GetExternalInputs: func(_ context.Context, node physical.Node) []executor.Pipeline { + GetExternalInputs: func(_ context.Context, node physicalpb.Node) []executor.Pipeline { streams := job.Task.Sources[node] if len(streams) == 0 { return nil diff --git a/pkg/engine/internal/workflow/task.go b/pkg/engine/internal/workflow/task.go index 24666bc33e77f..c428aab3242d1 100644 --- a/pkg/engine/internal/workflow/task.go +++ b/pkg/engine/internal/workflow/task.go @@ -3,7 +3,7 @@ package workflow import ( "github.com/oklog/ulid/v2" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" ) // A Task is a single unit of work within a workflow. Each Task is a partition @@ -16,15 +16,15 @@ type Task struct { TenantID string // Fragment is the local physical plan that this Task represents. - Fragment *physical.Plan + Fragment *physicalpb.Plan // Sources defines which Streams physical nodes read from. Sources are only // defined for nodes in the Fragment which read data across task boundaries. - Sources map[physical.Node][]*Stream + Sources map[physicalpb.Node][]*Stream // Sinks defines which Streams physical nodes write to. Sinks are only // defined for nodes in the Fragment which write data across task boundaries. - Sinks map[physical.Node][]*Stream + Sinks map[physicalpb.Node][]*Stream } // ID returns the string form of the Task's ULID. diff --git a/pkg/engine/internal/workflow/workflow.go b/pkg/engine/internal/workflow/workflow.go index 7c60a8e8d0cb4..172bc8453d708 100644 --- a/pkg/engine/internal/workflow/workflow.go +++ b/pkg/engine/internal/workflow/workflow.go @@ -12,7 +12,7 @@ import ( "github.com/oklog/ulid/v2" "github.com/grafana/loki/v3/pkg/engine/internal/executor" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" "github.com/grafana/loki/v3/pkg/logqlmodel/stats" ) @@ -40,7 +40,7 @@ type Workflow struct { // cannot be partitioned into a Workflow. // // The provided Runner will be used for Workflow execution. -func New(logger log.Logger, tenantID string, runner Runner, plan *physical.Plan) (*Workflow, error) { +func New(logger log.Logger, tenantID string, runner Runner, plan *physicalpb.Plan) (*Workflow, error) { graph, err := planWorkflow(tenantID, plan) if err != nil { return nil, err diff --git a/pkg/engine/internal/workflow/workflow_planner.go b/pkg/engine/internal/workflow/workflow_planner.go index 40b6219f94f97..872bc6fd4b334 100644 --- a/pkg/engine/internal/workflow/workflow_planner.go +++ b/pkg/engine/internal/workflow/workflow_planner.go @@ -7,7 +7,7 @@ import ( "github.com/oklog/ulid/v2" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" ) @@ -15,7 +15,7 @@ import ( type planner struct { tenantID string graph dag.Graph[*Task] - physical *physical.Plan + physical *physicalpb.Plan streamWriters map[*Stream]*Task // Lookup of stream to which task writes to it } @@ -24,7 +24,7 @@ type planner struct { // // planWorkflow returns an error if the provided physical plan does not // have exactly one root node, or if the physical plan cannot be partitioned. -func planWorkflow(tenantID string, plan *physical.Plan) (dag.Graph[*Task], error) { +func planWorkflow(tenantID string, plan *physicalpb.Plan) (dag.Graph[*Task], error) { root, err := plan.Root() if err != nil { return dag.Graph[*Task]{}, err @@ -45,7 +45,7 @@ func planWorkflow(tenantID string, plan *physical.Plan) (dag.Graph[*Task], error // Process builds a set of tasks from a root physical plan node. Built tasks are // added to p.graph. -func (p *planner) Process(root physical.Node) error { +func (p *planner) Process(root physicalpb.Node) error { _, err := p.processNode(root, true) return err } @@ -57,12 +57,12 @@ func (p *planner) Process(root physical.Node) error { // The resulting task is the task immediately produced by node, which callers // can use to add edges. All tasks, including those produced in recursive calls // to processNode, are added into p.Graph. -func (p *planner) processNode(node physical.Node, splitOnBreaker bool) (*Task, error) { +func (p *planner) processNode(node physicalpb.Node, splitOnBreaker bool) (*Task, error) { var ( // taskPlan is the in-progress physical plan for an individual task. - taskPlan dag.Graph[physical.Node] + taskPlan dag.Graph[physicalpb.Node] - sources = make(map[physical.Node][]*Stream) + sources = make(map[physicalpb.Node][]*Stream) // childrenTasks is the slice of immediate Tasks produced by processing // the children of node. @@ -73,9 +73,9 @@ func (p *planner) processNode(node physical.Node, splitOnBreaker bool) (*Task, e taskPlan.Add(node) var ( - stack = make(stack[physical.Node], 0, p.physical.Len()) - visited = make(map[physical.Node]struct{}, p.physical.Len()) - nodeTasks = make(map[physical.Node][]*Task, p.physical.Len()) + stack = make(stack[physicalpb.Node], 0, len(p.physical.Nodes)) + visited = make(map[physicalpb.Node]struct{}, len(p.physical.Nodes)) + nodeTasks = make(map[physicalpb.Node][]*Task, len(p.physical.Nodes)) ) stack.Push(node) @@ -118,11 +118,11 @@ func (p *planner) processNode(node physical.Node, splitOnBreaker bool) (*Task, e sources[next] = append(sources[next], stream) } - case child.Type() == physical.NodeTypeParallelize: + case child.Kind() == physicalpb.NodeKindParallelize: childTasks, found := nodeTasks[child] if !found { // Split the pipeline breaker into its own set of tasks. - tasks, err := p.processParallelizeNode(child.(*physical.Parallelize)) + tasks, err := p.processParallelizeNode(child.ToPlanNode().GetParallelize()) if err != nil { return nil, err } @@ -145,7 +145,7 @@ func (p *planner) processNode(node physical.Node, splitOnBreaker bool) (*Task, e // Add child node into the plan (if we haven't already) and // retain existing edges. taskPlan.Add(child) - _ = taskPlan.AddEdge(dag.Edge[physical.Node]{ + _ = taskPlan.AddEdge(dag.Edge[physicalpb.Node]{ Parent: next, Child: child, }) @@ -158,9 +158,9 @@ func (p *planner) processNode(node physical.Node, splitOnBreaker bool) (*Task, e task := &Task{ ULID: ulid.Make(), TenantID: p.tenantID, - Fragment: physical.FromGraph(taskPlan), + Fragment: physicalpb.FromGraph(taskPlan), Sources: sources, - Sinks: make(map[physical.Node][]*Stream), + Sinks: make(map[physicalpb.Node][]*Stream), } p.graph.Add(task) @@ -212,13 +212,13 @@ func (p *planner) removeSink(sink *Stream) error { } // isPipelineBreaker returns true if the node is a pipeline breaker. -func isPipelineBreaker(node physical.Node) bool { +func isPipelineBreaker(node physicalpb.Node) bool { // TODO(rfratto): Should this information be exposed by the node itself? A // decision on this should wait until we're able to serialize the node over // the network, since that might impact how we're able to define this at the // node level. - switch node.Type() { - case physical.NodeTypeTopK, physical.NodeTypeRangeAggregation, physical.NodeTypeVectorAggregation: + switch node.Kind() { + case physicalpb.NodeKindTopK, physicalpb.NodeKindAggregateRange, physicalpb.NodeKindAggregateVector: return true } @@ -226,7 +226,7 @@ func isPipelineBreaker(node physical.Node) bool { } // processParallelizeNode builds a set of tasks for a Parallelize node. -func (p *planner) processParallelizeNode(node *physical.Parallelize) ([]*Task, error) { +func (p *planner) processParallelizeNode(node *physicalpb.Parallelize) ([]*Task, error) { // Parallelize nodes are used as a marker task for splitting a branch of the // query plan into many distributed tasks. // @@ -303,7 +303,7 @@ func (p *planner) processParallelizeNode(node *physical.Parallelize) ([]*Task, e // The sources of the template task need to be replaced with new unique // streams. - shardSources := make(map[physical.Node][]*Stream, len(templateTask.Sources)) + shardSources := make(map[physicalpb.Node][]*Stream, len(templateTask.Sources)) for node, templateStreams := range templateTask.Sources { shardStreams := make([]*Stream, 0, len(templateStreams)) @@ -328,9 +328,9 @@ func (p *planner) processParallelizeNode(node *physical.Parallelize) ([]*Task, e ULID: ulid.Make(), TenantID: p.tenantID, - Fragment: physical.FromGraph(*shardedPlan), + Fragment: physicalpb.FromGraph(*shardedPlan), Sources: shardSources, - Sinks: make(map[physical.Node][]*Stream), + Sinks: make(map[physicalpb.Node][]*Stream), } p.graph.Add(partition) @@ -367,16 +367,16 @@ func (p *planner) processParallelizeNode(node *physical.Parallelize) ([]*Task, e // If there is no shardable leaf node reachable from root, findShardableNode // returns nil. findShardableNode returns an error if there are two shardable // leaf nodes. -func findShardableNode(graph *dag.Graph[physical.Node], root physical.Node) (physical.ShardableNode, error) { - var found physical.ShardableNode +func findShardableNode(graph *dag.Graph[physicalpb.Node], root physicalpb.Node) (physicalpb.ShardableNode, error) { + var found physicalpb.ShardableNode - err := graph.Walk(root, func(n physical.Node) error { + err := graph.Walk(root, func(n physicalpb.Node) error { isLeaf := len(graph.Children(n)) == 0 if !isLeaf { return nil } - shardable, ok := n.(physical.ShardableNode) + shardable, ok := n.(physicalpb.ShardableNode) if !ok { return nil } else if found != nil { diff --git a/pkg/engine/internal/workflow/workflow_planner_test.go b/pkg/engine/internal/workflow/workflow_planner_test.go index 73241a453e726..f2fd8b239a04c 100644 --- a/pkg/engine/internal/workflow/workflow_planner_test.go +++ b/pkg/engine/internal/workflow/workflow_planner_test.go @@ -4,11 +4,12 @@ import ( "strings" "testing" - "github.com/oklog/ulid/v2" + oklogULID "github.com/oklog/ulid/v2" "github.com/stretchr/testify/require" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" + "github.com/grafana/loki/v3/pkg/engine/internal/util/ulid" ) // TODO(rfratto): Once physical plans can be serializable, we should be able to @@ -24,10 +25,11 @@ func Test_planWorkflow(t *testing.T) { t.Run("no pipeline breakers", func(t *testing.T) { ulidGen := ulidGenerator{} - var physicalGraph dag.Graph[physical.Node] - physicalGraph.Add(&physical.DataObjScan{}) + var physicalGraph dag.Graph[physicalpb.Node] + scanID := physicalpb.PlanNodeID{Value: ulid.New()} + physicalGraph.Add(&physicalpb.DataObjScan{Id: scanID}) - physicalPlan := physical.FromGraph(physicalGraph) + physicalPlan := physicalpb.FromGraph(physicalGraph) graph, err := planWorkflow("", physicalPlan) require.NoError(t, err) @@ -38,7 +40,7 @@ func Test_planWorkflow(t *testing.T) { expectOuptut := strings.TrimSpace(` Task 00000000000000000000000001 ------------------------------- -DataObjScan location= streams=0 section_id=0 projections=() +DataObjScan location= streams=0 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 `) actualOutput := Sprint(&Workflow{graph: graph}) @@ -47,18 +49,17 @@ DataObjScan location= streams=0 section_id=0 projections=() t.Run("ends with one pipeline breaker", func(t *testing.T) { ulidGen := ulidGenerator{} - - var physicalGraph dag.Graph[physical.Node] + var physicalGraph dag.Graph[physicalpb.Node] var ( - scan = physicalGraph.Add(&physical.DataObjScan{}) - rangeAgg = physicalGraph.Add(&physical.RangeAggregation{}) + scanID = physicalpb.PlanNodeID{Value: ulid.New()} + rangeAggID = physicalpb.PlanNodeID{Value: ulid.New()} + scan = physicalGraph.Add(&physicalpb.DataObjScan{Id: scanID}) + rangeAgg = physicalGraph.Add(&physicalpb.AggregateRange{Id: rangeAggID}) ) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: rangeAgg, Child: scan}) - - physicalPlan := physical.FromGraph(physicalGraph) - + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg, Child: scan}) + physicalPlan := physicalpb.FromGraph(physicalGraph) graph, err := planWorkflow("", physicalPlan) require.NoError(t, err) require.Equal(t, 1, graph.Len()) @@ -68,8 +69,8 @@ DataObjScan location= streams=0 section_id=0 projections=() expectOuptut := strings.TrimSpace(` Task 00000000000000000000000001 ------------------------------- -RangeAggregation operation=invalid start=0001-01-01T00:00:00Z end=0001-01-01T00:00:00Z step=0s range=0s -└── DataObjScan location= streams=0 section_id=0 projections=() +AggregateRange operation=AGGREGATE_RANGE_OP_INVALID start=1970-01-01T00:00:00Z end=1970-01-01T00:00:00Z step=0s range=0s +└── DataObjScan location= streams=0 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 `) actualOutput := Sprint(&Workflow{graph: graph}) @@ -79,18 +80,21 @@ RangeAggregation operation=invalid start=0001-01-01T00:00:00Z end=0001-01-01T00: t.Run("split on pipeline breaker", func(t *testing.T) { ulidGen := ulidGenerator{} - var physicalGraph dag.Graph[physical.Node] + var physicalGraph dag.Graph[physicalpb.Node] var ( - scan = physicalGraph.Add(&physical.DataObjScan{}) - rangeAgg = physicalGraph.Add(&physical.RangeAggregation{}) - vectorAgg = physicalGraph.Add(&physical.VectorAggregation{}) + scanID = physicalpb.PlanNodeID{Value: ulid.New()} + rangeAggID = physicalpb.PlanNodeID{Value: ulid.New()} + vectorAggID = physicalpb.PlanNodeID{Value: ulid.New()} + scan = physicalGraph.Add(&physicalpb.DataObjScan{Id: scanID}) + rangeAgg = physicalGraph.Add(&physicalpb.AggregateRange{Id: rangeAggID}) + vectorAgg = physicalGraph.Add(&physicalpb.AggregateVector{Id: vectorAggID}) ) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: rangeAgg, Child: scan}) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: vectorAgg, Child: rangeAgg}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg, Child: scan}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: vectorAgg, Child: rangeAgg}) - physicalPlan := physical.FromGraph(physicalGraph) + physicalPlan := physicalpb.FromGraph(physicalGraph) graph, err := planWorkflow("", physicalPlan) require.NoError(t, err) @@ -101,14 +105,14 @@ RangeAggregation operation=invalid start=0001-01-01T00:00:00Z end=0001-01-01T00: expectOuptut := strings.TrimSpace(` Task 00000000000000000000000001 ------------------------------- -VectorAggregation operation=invalid +AggregateVector operation=AGGREGATE_VECTOR_OP_INVALID └── @source stream=00000000000000000000000003 Task 00000000000000000000000002 ------------------------------- -RangeAggregation operation=invalid start=0001-01-01T00:00:00Z end=0001-01-01T00:00:00Z step=0s range=0s +AggregateRange operation=AGGREGATE_RANGE_OP_INVALID start=1970-01-01T00:00:00Z end=1970-01-01T00:00:00Z step=0s range=0s │ └── @sink stream=00000000000000000000000003 -└── DataObjScan location= streams=0 section_id=0 projections=() +└── DataObjScan location= streams=0 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 `) actualOutput := Sprint(&Workflow{graph: graph}) @@ -118,32 +122,39 @@ RangeAggregation operation=invalid start=0001-01-01T00:00:00Z end=0001-01-01T00: t.Run("split on parallelize", func(t *testing.T) { ulidGen := ulidGenerator{} - var physicalGraph dag.Graph[physical.Node] + var physicalGraph dag.Graph[physicalpb.Node] var ( - vectorAgg = physicalGraph.Add(&physical.VectorAggregation{}) - rangeAgg = physicalGraph.Add(&physical.RangeAggregation{}) - - parallelize = physicalGraph.Add(&physical.Parallelize{}) - - filter = physicalGraph.Add(&physical.Filter{}) - parse = physicalGraph.Add(&physical.ParseNode{Kind: physical.ParserLogfmt}) - scanSet = physicalGraph.Add(&physical.ScanSet{ - Targets: []*physical.ScanTarget{ - {Type: physical.ScanTypeDataObject, DataObject: &physical.DataObjScan{Location: "a"}}, - {Type: physical.ScanTypeDataObject, DataObject: &physical.DataObjScan{Location: "b"}}, - {Type: physical.ScanTypeDataObject, DataObject: &physical.DataObjScan{Location: "c"}}, + vectorAggID = physicalpb.PlanNodeID{Value: ulid.New()} + rangeAggID = physicalpb.PlanNodeID{Value: ulid.New()} + parallelizeID = physicalpb.PlanNodeID{Value: ulid.New()} + filterID = physicalpb.PlanNodeID{Value: ulid.New()} + parseID = physicalpb.PlanNodeID{Value: ulid.New()} + scanSetID = physicalpb.PlanNodeID{Value: ulid.New()} + + vectorAgg = physicalGraph.Add(&physicalpb.AggregateVector{Id: vectorAggID}) + rangeAgg = physicalGraph.Add(&physicalpb.AggregateRange{Id: rangeAggID}) + + parallelize = physicalGraph.Add(&physicalpb.Parallelize{Id: parallelizeID}) + + filter = physicalGraph.Add(&physicalpb.Filter{Id: filterID}) + parse = physicalGraph.Add(&physicalpb.Parse{Operation: physicalpb.PARSE_OP_LOGFMT, Id: parseID}) + scanSet = physicalGraph.Add(&physicalpb.ScanSet{Id: scanSetID, + Targets: []*physicalpb.ScanTarget{ + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Location: "a"}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Location: "b"}}, + {Type: physicalpb.SCAN_TYPE_DATA_OBJECT, DataObject: &physicalpb.DataObjScan{Location: "c"}}, }, }) ) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: vectorAgg, Child: rangeAgg}) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: rangeAgg, Child: parallelize}) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: parallelize, Child: filter}) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: filter, Child: parse}) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: parse, Child: scanSet}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: vectorAgg, Child: rangeAgg}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg, Child: parallelize}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: parallelize, Child: filter}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: filter, Child: parse}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: parse, Child: scanSet}) - physicalPlan := physical.FromGraph(physicalGraph) + physicalPlan := physicalpb.FromGraph(physicalGraph) graph, err := planWorkflow("", physicalPlan) require.NoError(t, err) @@ -154,12 +165,12 @@ RangeAggregation operation=invalid start=0001-01-01T00:00:00Z end=0001-01-01T00: expectOuptut := strings.TrimSpace(` Task 00000000000000000000000001 ------------------------------- -VectorAggregation operation=invalid +AggregateVector operation=AGGREGATE_VECTOR_OP_INVALID └── @source stream=00000000000000000000000006 Task 00000000000000000000000002 ------------------------------- -RangeAggregation operation=invalid start=0001-01-01T00:00:00Z end=0001-01-01T00:00:00Z step=0s range=0s +AggregateRange operation=AGGREGATE_RANGE_OP_INVALID start=1970-01-01T00:00:00Z end=1970-01-01T00:00:00Z step=0s range=0s ├── @source stream=00000000000000000000000007 ├── @source stream=00000000000000000000000008 ├── @source stream=00000000000000000000000009 @@ -169,22 +180,22 @@ Task 00000000000000000000000003 ------------------------------- Filter │ └── @sink stream=00000000000000000000000007 -└── Parse kind=logfmt - └── DataObjScan location=a streams=0 section_id=0 projections=() +└── Parse kind=PARSE_OP_LOGFMT + └── DataObjScan location=a streams=0 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 Task 00000000000000000000000004 ------------------------------- Filter │ └── @sink stream=00000000000000000000000008 -└── Parse kind=logfmt - └── DataObjScan location=b streams=0 section_id=0 projections=() +└── Parse kind=PARSE_OP_LOGFMT + └── DataObjScan location=b streams=0 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 Task 00000000000000000000000005 ------------------------------- Filter │ └── @sink stream=00000000000000000000000009 -└── Parse kind=logfmt - └── DataObjScan location=c streams=0 section_id=0 projections=() +└── Parse kind=PARSE_OP_LOGFMT + └── DataObjScan location=c streams=0 section_id=0 projections=() direction=SORT_ORDER_INVALID limit=0 `) actualOutput := Sprint(&Workflow{graph: graph}) @@ -199,8 +210,8 @@ func requireUniqueStreams(t testing.TB, g dag.Graph[*Task]) { t.Helper() type streamInfo struct { - Reader physical.Node - Writer physical.Node + Reader physicalpb.Node + Writer physicalpb.Node } streamInfos := make(map[*Stream]*streamInfo) @@ -271,7 +282,7 @@ type ulidGenerator struct { lastCounter uint64 } -func (g *ulidGenerator) Make() ulid.ULID { +func (g *ulidGenerator) Make() oklogULID.ULID { g.lastCounter++ value := g.lastCounter @@ -281,5 +292,5 @@ func (g *ulidGenerator) Make() ulid.ULID { for i := range 8 { ulidBytes[15-i] = byte(value >> (8 * i)) } - return ulid.ULID(ulidBytes) + return oklogULID.ULID(ulidBytes) } diff --git a/pkg/engine/internal/workflow/workflow_test.go b/pkg/engine/internal/workflow/workflow_test.go index eaecc2a7f1f3e..a23dd8d68fa46 100644 --- a/pkg/engine/internal/workflow/workflow_test.go +++ b/pkg/engine/internal/workflow/workflow_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/loki/v3/pkg/engine/internal/executor" - "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical" + "github.com/grafana/loki/v3/pkg/engine/internal/planner/physical/physicalpb" "github.com/grafana/loki/v3/pkg/engine/internal/util/dag" ) @@ -26,18 +26,18 @@ import ( // Some of these assertions are handled by [fakeRunner], which returns an error // when used improperly. func Test(t *testing.T) { - var physicalGraph dag.Graph[physical.Node] + var physicalGraph dag.Graph[physicalpb.Node] var ( - scan = physicalGraph.Add(&physical.DataObjScan{}) - rangeAgg = physicalGraph.Add(&physical.RangeAggregation{}) - vectorAgg = physicalGraph.Add(&physical.VectorAggregation{}) + scan = physicalGraph.Add(&physicalpb.DataObjScan{}) + rangeAgg = physicalGraph.Add(&physicalpb.AggregateRange{}) + vectorAgg = physicalGraph.Add(&physicalpb.AggregateVector{}) ) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: rangeAgg, Child: scan}) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: vectorAgg, Child: rangeAgg}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg, Child: scan}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: vectorAgg, Child: rangeAgg}) - physicalPlan := physical.FromGraph(physicalGraph) + physicalPlan := physicalpb.FromGraph(physicalGraph) fr := newFakeRunner() @@ -82,18 +82,18 @@ func Test(t *testing.T) { // TestCancellation tasks that a task entering a terminal state cancels all // downstream tasks. func TestCancellation(t *testing.T) { - var physicalGraph dag.Graph[physical.Node] + var physicalGraph dag.Graph[physicalpb.Node] var ( - scan = physicalGraph.Add(&physical.DataObjScan{}) - rangeAgg = physicalGraph.Add(&physical.RangeAggregation{}) - vectorAgg = physicalGraph.Add(&physical.VectorAggregation{}) + scan = physicalGraph.Add(&physicalpb.DataObjScan{}) + rangeAgg = physicalGraph.Add(&physicalpb.AggregateRange{}) + vectorAgg = physicalGraph.Add(&physicalpb.AggregateVector{}) ) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: rangeAgg, Child: scan}) - _ = physicalGraph.AddEdge(dag.Edge[physical.Node]{Parent: vectorAgg, Child: rangeAgg}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: rangeAgg, Child: scan}) + _ = physicalGraph.AddEdge(dag.Edge[physicalpb.Node]{Parent: vectorAgg, Child: rangeAgg}) - physicalPlan := physical.FromGraph(physicalGraph) + physicalPlan := physicalpb.FromGraph(physicalGraph) terminalStates := []TaskState{TaskStateCancelled, TaskStateCancelled, TaskStateFailed} for _, state := range terminalStates { diff --git a/pkg/limits/store.go b/pkg/limits/store.go index 0f0ac05953497..b4661152af945 100644 --- a/pkg/limits/store.go +++ b/pkg/limits/store.go @@ -40,7 +40,7 @@ type iterateFunc func(tenant string, partition int32, stream streamUsage) // getPolicyBucketAndLimit determines which policy bucket to use and the max streams limit // for a given tenant and policy. Returns the policy bucket name and the max streams limit. -// The policy bucket will be the input policy name only if the max streams limit is overriden for the policy. +// The policy bucket will be the input policy name only if the max streams limit is overridden for the policy. func (s *usageStore) getPolicyBucketAndStreamsLimit(tenant, policy string) (policyBucket string, maxStreams uint64) { defaultMaxStreams := uint64(s.limits.MaxGlobalStreamsPerUser(tenant) / s.numPartitions) diff --git a/pkg/logql/log/label_filter.go b/pkg/logql/log/label_filter.go index 6de272dfc1c98..e087913801a98 100644 --- a/pkg/logql/log/label_filter.go +++ b/pkg/logql/log/label_filter.go @@ -398,7 +398,7 @@ func (s *LineFilterLabelFilter) String() string { } else { rStr = fmt.Sprintf("`%s`", rStr) } - str := fmt.Sprintf("%s%s%s", s.Matcher.Name, s.Matcher.Type, rStr) + str := fmt.Sprintf("%s%s%s", s.Name, s.Type, rStr) return str } return s.Matcher.String()