// SPDX-License-Identifier: Apache-2.0
syntax = "proto3";

package substrait;

import "substrait/algebra.proto";
import "substrait/extensions/extensions.proto";
import "substrait/type.proto";

option csharp_namespace = "Substrait.Protobuf";
option go_package = "github.com/substrait-io/substrait-protobuf/go/substraitpb";
option java_multiple_files = true;
option java_package = "io.substrait.proto";

// Either a relation or root relation
message PlanRel {
  oneof rel_type {
    // Any relation (used for references and CTEs)
    Rel rel = 1;
    // The root of a relation tree
    RelRoot root = 2;
  }
}

// Describe a set of operations to complete.
// For compactness sake, identifiers are normalized at the plan level.
message Plan {
  reserved 1;

  // Substrait version of the plan. Optional up to 0.17.0, required for later
  // versions.
  Version version = 6;

  // a list of extension URNs this plan may depend on
  repeated substrait.extensions.SimpleExtensionURN extension_urns = 8;

  // a list of extensions this plan may depend on
  repeated substrait.extensions.SimpleExtensionDeclaration extensions = 2;

  // one or more relation trees that are associated with this plan.
  repeated PlanRel relations = 3;

  // additional extensions associated with this plan.
  substrait.extensions.AdvancedExtension advanced_extensions = 4;

  // A list of com.google.Any entities that this plan may use. Can be used to
  // warn if some embedded message types are unknown. Note that this list may
  // include message types that are ignorable (optimizations) or that are
  // unused. In many cases, a consumer may be able to work with a plan even if
  // one or more message types defined here are unknown.
  repeated string expected_type_urls = 5;

  // An optional list of bindings for dynamic parameters used in this plan.
  // Each binding maps a parameter_anchor to its corresponding runtime value.
  repeated DynamicParameterBinding parameter_bindings = 7;

  // An optional list of type aliases. Types can be specified here once, and
  // then referenced within the plan using the TypeAliasReference type. This
  // feature is intended to assist with the usability of parameterized types,
  // which require that all parameters be specified when they are declared.
  // This can bloat plans with redundant redeclarations, especially if the
  // parameterized types being declared have many parameters (e.g., struct with
  // many fields, nested parameterized types, string as a type parameter).
  repeated TypeAlias type_aliases = 9;

  // Execution behavior settings for this plan, required.
  ExecutionBehavior execution_behavior = 10;
}

// This message type can be used to deserialize only the version of a Substrait
// Plan message. This prevents deserialization errors when there were breaking
// changes between the Substrait version of the tool that produced the plan and
// the Substrait version used to deserialize it, such that a consumer can emit
// a more helpful error message in this case.
message PlanVersion {
  Version version = 6;
}

message Version {
  // Substrait version number.
  uint32 major_number = 1;
  uint32 minor_number = 2;
  uint32 patch_number = 3;

  // If a particular version of Substrait is used that does not correspond to
  // a version number exactly (for example when using an unofficial fork or
  // using a version that is not yet released or is between versions), set this
  // to the full git hash of the utilized commit of
  // https://github.com/substrait-io/substrait (or fork thereof), represented
  // using a lowercase hex ASCII string 40 characters in length. The version
  // number above should be set to the most recent version tag in the history
  // of that commit.
  string git_hash = 4;

  // Identifying information for the producer that created this plan. Under
  // ideal circumstances, consumers should not need this information. However,
  // it is foreseen that consumers may need to work around bugs in particular
  // producers in practice, and therefore may need to know which producer
  // created the plan.
  string producer = 5;
}

// Represents a binding for a dynamic parameter.
message DynamicParameterBinding {
  // The parameter anchor that identifies the dynamic parameter reference.
  // 0 is a valid anchor/reference, but prefer non-zero values for ergonomics.
  uint32 parameter_anchor = 1;

  // The literal value assigned to the parameter at runtime.
  // The type of the literal needs to match the type of the corresponding
  // DynamicParameter expression in the plan.
  Expression.Literal value = 2;
}

// ExecutionBehavior specifies the execution behavior for plan evaluation.
message ExecutionBehavior {
  // Defines the scope of execution context variable evaluation during plan
  // execution.
  VariableEvaluationMode variable_eval_mode = 1;

  // VariableEvaluationMode specifies the frequency and scope of execution
  // context variable evaluation.
  enum VariableEvaluationMode {
    VARIABLE_EVALUATION_MODE_UNSPECIFIED = 0;
    // Variables are evaluated once per Substrait plan execution.
    VARIABLE_EVALUATION_MODE_PER_PLAN = 1;
    // Variables are evaluated once per record during execution.
    VARIABLE_EVALUATION_MODE_PER_RECORD = 2;
  }
}
