/*
 * Copyright (c) 2015, 2025, Oracle and/or its affiliates.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2.0,
 * as published by the Free Software Foundation.
 *
 * This program is designed to work with certain software (including
 * but not limited to OpenSSL) that is licensed under separate terms,
 * as designated in a particular file or component or in included license
 * documentation.  The authors of MySQL hereby grant you an additional
 * permission to link the program and your derivative works with the
 * separately licensed software that they have either included with
 * the program or referenced in the documentation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License, version 2.0, for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
 */
syntax = "proto2";

// ifdef PROTOBUF_LITE: option optimize_for = LITE_RUNTIME;

/**
@namespace Mysqlx::Expr
@brief Expressions

Expression syntax

expr is the fundamental structure in various places of the SQL language:

-  ``SELECT <expr> AS ...``

-  ``WHERE <expr>``

The structures can be used to:
-  build an Item-tree in the MySQL Server
-  generate SQL from it
-  use as filter condition in CRUD ``Find()``, ``Update()``, and
   ``Delete()`` calls.
*/
package Mysqlx.Expr;
option java_package = "com.mysql.cj.x.protobuf";

import "mysqlx_datatypes.proto";

/**
The "root" of the expression tree.

If expression type is PLACEHOLDER, then it refers to the value
of a parameter specified when executing a statement (see args
field of StmtExecute command). Field position (which must be
present for such an expression) gives 0-based position of the
parameter in the parameter list.

@par production list
@code{unparsed}
expr: operator |
    : identifier |
    : function_call |
    : variable |
    : literal |
    : object |
    : array |
    : placeholder
@endcode
*/
message Expr {
  enum Type {
    IDENT          = 1;
    LITERAL        = 2;
    VARIABLE       = 3;
    FUNC_CALL      = 4;
    OPERATOR       = 5;
    PLACEHOLDER    = 6;
    OBJECT         = 7;
    ARRAY          = 8;
  }

  required Type type = 1;

  optional ColumnIdentifier identifier = 2;
  optional string       variable = 3;
  optional Mysqlx.Datatypes.Scalar literal = 4;
  optional FunctionCall function_call = 5;
  optional Operator     operator = 6;
  optional uint32       position = 7;
  optional Object       object = 8;
  optional Array        array = 9;
}

/**
Identifier: name, schame.name

@par production list
@code{unparsed}
  identifier: string "." string |
            : string
@endcode
*/
message Identifier {
  required string name = 1;
  optional string schema_name = 2;
}

/**
Document path item

@par production list
@code{unparsed}
  document_path: path_item | path_item document_path
  path_item    : member | array_index | "**"
  member       : "." string | "." "*"
  array_index  : "[" number "]" | "[" "*" "]"
@endcode
*/
message DocumentPathItem {
  enum Type {
    /**  .member */
    MEMBER = 1;

    /** \.* */
    MEMBER_ASTERISK = 2;

    /** [index] */
    ARRAY_INDEX = 3;

    /** [*] */
    ARRAY_INDEX_ASTERISK = 4;

    /** ** */
    DOUBLE_ASTERISK = 5;
  }
  required Type type = 1;
  optional string value = 2;

  /** used in case of ARRY_INDEX */
  optional uint32 index = 3;
}


/**
Column identifier

for table: col\@doc_path, tbl.col\@doc_path col, tbl.col, schema.tbl.col
for document collection: doc_path
//
@par production list
@code{unparsed}
  col_identifier: string "." string "." string |
                : string "." string |
                : string |
                : string "." string "." string "@" document_path |
                : string "." string "@" document_path |
                : string "@" document_path |
                : document_path
   document_path: member | arrayLocation | doubleAsterisk
   member = "." string | "." "*"
   arrayLocation = "[" index "]" | "[" "*" "]"
   doubleAsterisk = "**"
@endcode
*/
message ColumnIdentifier {
  /** document path */
  repeated Mysqlx.Expr.DocumentPathItem document_path = 1;

  /** name of column */
  optional string name = 2;

  /** name of table */
  optional string table_name = 3;

  /** name of schema */
  optional string schema_name = 4;
}

/**
Function call: ``func(a, b, "1", 3)``

@par production list
@code{unparsed}
  function_call: `identifier` "(" [ `expr` ["," `expr` ]* ] ")"
@endcode
*/
message FunctionCall {
  /** identifier of function; at least name of it */
  required Identifier name = 1;

  /** list of parameters */
  repeated Expr param = 2;
}

/**
Operator: ``<<(a, b)``

@note
    Non-authoritative list of operators implemented (case sensitive):
    - Nullary
      + ``*``
      + ``default``
    - Unary
      + ``!``
      + ``sign_plus``
      + ``sign_minus``
      + ``~``
    - Binary
      + ``&&``
      + ``||``
      + ``xor``
      + ``==``
      + ``!=``
      + ``>``
      + ``>=``
      + ``<``
      + ``<=``
      + ``&``
      + ``|``
      + ``^``
      + ``<<``
      + ``>>``
      + ``+``
      + ``-``
      + ``*``
      + ``/``
      + ``div``
      + ``%``
      + ``is``
      + ``is_not``
      + ``regexp``
      + ``not_regexp``
      + ``like``
      + ``not_like``
      + ``cast``
      + ``cont_in``
      + ``not_cont_in``
      + ``overlaps``
      + ``not_overlaps``
    - Using special representation, with more than 2 params
      + ``in`` (param[0] IN (param[1], param[2], ...))
      + ``not_in`` (param[0] NOT IN (param[1], param[2], ...))
    - Ternary
      + ``between``
      + ``between_not``
      + ``date_add``
      + ``date_sub``

@par

@note Units for date_add/date_sub
  - ``MICROSECOND``
  - ``SECOND``
  - ``MINUTE``
  - ``HOUR``
  - ``DAY``
  - ``WEEK``
  - ``MONTH``
  - ``QUARTER``
  - ``YEAR``
  - ``SECOND_MICROSECOND``
  - ``MINUTE_MICROSECOND``
  - ``MINUTE_SECOND``
  - ``HOUR_MICROSECOND``
  - ``HOUR_SECOND``
  - ``HOUR_MINUTE``
  - ``DAY_MICROSECOND``
  - ``DAY_SECOND``
  - ``DAY_MINUTE``
  - ``DAY_HOUR``

@par

@note Types for cast
  - ``BINARY[(N)]``
  - ``CHAR[(N)]``
  - ``DATE``
  - ``DATETIME``
  - ``DECIMAL[(M[,D])]``
  - ``JSON``
  - ``SIGNED [INTEGER]``
  - ``TIME``
  - ``UNSIGNED [INTEGER]``

@par production list
@code{unparsed}
  operator: `name` "(" [ `expr` ["," `expr` ]* ] ")"
@endcode
*/

message Operator {
  /** name of operator */
  required string name = 1;

  /** list of parameters */
  repeated Expr param = 2;
}

/**
An object (with expression values)
*/
message Object {
  message ObjectField {
    /** identifier of field */
    required string key = 1;
    /** value of field */
    required Expr value = 2;
  }

  /** list of fields */
  repeated ObjectField fld = 1;
}

/**
An array of expressions
*/
message Array {
  /** list of values */
  repeated Expr value = 1;
}
