syntax = "proto3";
package milvus.proto.plan;

option go_package = "github.com/milvus-io/milvus/pkg/proto/planpb";
import "schema.proto";

enum OpType {
  Invalid = 0;
  GreaterThan = 1;
  GreaterEqual = 2;
  LessThan = 3;
  LessEqual = 4;
  Equal = 5;
  NotEqual = 6;
  PrefixMatch = 7;  // startsWith
  PostfixMatch = 8; // endsWith
  Match = 9;        // like
  Range = 10;       // for case 1 < a < b
  In = 11;          // TODO:: used for term expr
  NotIn = 12;
};

enum ArithOpType {
  Unknown = 0;
  Add = 1;
  Sub = 2;
  Mul = 3;
  Div = 4;
  Mod = 5;
  ArrayLength = 6;
};

enum VectorType {
  BinaryVector = 0;
  FloatVector = 1;
  Float16Vector = 2;
  BFloat16Vector = 3;
  SparseFloatVector = 4;
};

message GenericValue {
  oneof val {
    bool bool_val = 1;
    int64 int64_val = 2;
    double float_val = 3;
    string string_val = 4;
    Array array_val = 5;
  };
}

message Array {
  repeated GenericValue array = 1;
  bool same_type = 2;
  schema.DataType element_type = 3;
}

message QueryInfo {
  int64 topk = 1;
  string metric_type = 3;
  string search_params = 4;
  int64 round_decimal = 5;
  int64 group_by_field_id = 6;
  bool materialized_view_involved = 7;
}

message ColumnInfo {
  int64 field_id = 1;
  schema.DataType data_type = 2;
  bool is_primary_key = 3;
  bool is_autoID = 4;
  repeated string nested_path = 5;
  bool is_partition_key = 6;
  schema.DataType element_type = 7;
  bool is_clustering_key = 8;
}

message ColumnExpr {
  ColumnInfo info = 1;
}

message ExistsExpr {
  ColumnInfo info = 1;
}

message ValueExpr {
  GenericValue value = 1;
  string template_variable_name = 2;
}

message UnaryRangeExpr {
  ColumnInfo column_info = 1;
  OpType op = 2;
  GenericValue value = 3;
  string template_variable_name = 4;
}

message BinaryRangeExpr {
  ColumnInfo column_info = 1;
  bool lower_inclusive = 2;
  bool upper_inclusive = 3;
  GenericValue lower_value = 4;
  GenericValue upper_value = 5;
  string lower_template_variable_name = 6;
  string upper_template_variable_name = 7;
}

message CompareExpr {
  ColumnInfo left_column_info = 1;
  ColumnInfo right_column_info = 2;
  OpType op = 3;
}

message TermExpr {
  ColumnInfo column_info = 1;
  repeated GenericValue values = 2;
  bool is_in_field = 3;
  string template_variable_name = 4;
}

message JSONContainsExpr {
  ColumnInfo column_info = 1;
  repeated GenericValue elements = 2;
  // 0: invalid
  // 1: json_contains | array_contains
  // 2: json_contains_all | array_contains_all
  // 3: json_contains_any | array_contains_any
  enum JSONOp {
    Invalid = 0;
    Contains = 1;
    ContainsAll = 2;
    ContainsAny = 3;
  }
  JSONOp op = 3;
  bool elements_same_type = 4;
  string template_variable_name = 5;
}

message UnaryExpr {
  enum UnaryOp {
    Invalid = 0;
    Not = 1;
  };
  UnaryOp op = 1;
  Expr child = 2;
}

message BinaryExpr {
  enum BinaryOp {
    Invalid = 0;
    LogicalAnd = 1;
    LogicalOr = 2;
  }
  BinaryOp op = 1;
  Expr left = 2;
  Expr right = 3;
}

message BinaryArithOp {
  ColumnInfo column_info = 1;
  ArithOpType arith_op = 2;
  GenericValue right_operand = 3;
}

message BinaryArithExpr {
  Expr left = 1;
  Expr right = 2;
  ArithOpType op = 3;
}

message BinaryArithOpEvalRangeExpr {
  ColumnInfo column_info = 1;
  ArithOpType arith_op = 2;
  GenericValue right_operand = 3;
  OpType op = 4;
  GenericValue value = 5;
  string operand_template_variable_name = 6;
  string value_template_variable_name = 7;
}

message AlwaysTrueExpr {}

message Expr {
  oneof expr {
    TermExpr term_expr = 1;
    UnaryExpr unary_expr = 2;
    BinaryExpr binary_expr = 3;
    CompareExpr compare_expr = 4;
    UnaryRangeExpr unary_range_expr = 5;
    BinaryRangeExpr binary_range_expr = 6;
    BinaryArithOpEvalRangeExpr binary_arith_op_eval_range_expr = 7;
    BinaryArithExpr binary_arith_expr = 8;
    ValueExpr value_expr = 9;
    ColumnExpr column_expr = 10;
    ExistsExpr exists_expr = 11;
    AlwaysTrueExpr always_true_expr = 12;
    JSONContainsExpr json_contains_expr = 13;
  };
  bool is_template = 20;
}

message VectorANNS {
  VectorType vector_type = 1;
  int64 field_id = 2;
  Expr predicates = 3;
  QueryInfo query_info = 4;
  string placeholder_tag = 5;  // always be "$0"
}

message QueryPlanNode {
  Expr predicates = 1;
  bool is_count = 2;
  int64 limit = 3;
};

message PlanNode {
  oneof node {
    VectorANNS vector_anns = 1;
    Expr predicates = 2; // deprecated, use query instead.
    QueryPlanNode query = 4;
  }
  repeated int64 output_field_ids = 3;
  repeated string dynamic_fields = 5;
}
