/*
 * 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::Crud
@brief Basic CRUD operations

The CRUD operations work in a similar fashion as the SQL statements below:
 - @ref Mysqlx::Crud::Insert - ``INSERT INTO ...``
 - @ref Mysqlx::Crud::Find - ``SELECT ... FROM ...``
 - @ref Mysqlx::Crud::Update - ``UPDATE ... SET ...``
 - @ref Mysqlx::Crud::Delete - ``DELETE FROM ...``

Also operation related to manipulation of views:
 - @ref Mysqlx::Crud::CreateView - ``CREATE VIEW ... AS ...``
 - @ref Mysqlx::Crud::ModifyView - ``ALTER VIEW ... AS ...``
 - @ref Mysqlx::Crud::DropView - ``DROP VIEW ...``
*/

package Mysqlx.Crud;
option java_package = "com.mysql.cj.x.protobuf";

import "mysqlx.proto"; // comment_out_if PROTOBUF_LITE
import "mysqlx_expr.proto";
import "mysqlx_datatypes.proto";

message Column {
  optional string name = 1;
  optional string alias = 2;
  repeated Mysqlx.Expr.DocumentPathItem document_path = 3;
}

message Projection {
  /** the expression identifying an element from the source data,
      which can include a column identifier or any expression */
    required Mysqlx.Expr.Expr source = 1;
  /** optional alias. Required for DOCUMENTs (clients may use
      the source string as default) */
    optional string alias = 2;
}

/**
DataModel to use for filters, names, ...
*/
enum DataModel {
  DOCUMENT = 1;
  TABLE = 2;
}

message Collection {
  required string name = 1;
  optional string schema = 2;
}

message Limit {
  /** maximum rows to filter */
  required uint64 row_count = 1 /* ifdef PROTOBUF3 [jstype = JS_STRING] */;
  /** maximum rows to skip before applying the row_count */
  optional uint64 offset = 2 /* ifdef PROTOBUF3 [jstype = JS_STRING] */;
}

/**
LimitExpr, in comparison to Limit, is able to specify that row_count and
offset are placeholders.
This message support expressions of following types Expr/literal/UINT,
Expr/PLACEHOLDER.
*/
message LimitExpr {
  /** maximum rows to filter */
  required Mysqlx.Expr.Expr row_count = 1;

  /** maximum rows to skip before applying the row_count */
  optional Mysqlx.Expr.Expr offset = 2;
}

/**
Sort order
*/
message Order {
  enum Direction {
    ASC = 1;
    DESC = 2;
  }

  required Mysqlx.Expr.Expr expr = 1;
  optional Direction direction = 2 [ default=ASC ];
}

message UpdateOperation {
  enum UpdateType {
    /** only allowed for TABLE */
    SET = 1;

    /** no value (removes the identified path from a object or array) */
    ITEM_REMOVE = 2;

    /** sets the new value on the identified path */
    ITEM_SET = 3;

    /** replaces a value if the path exists */
    ITEM_REPLACE = 4;

    /** source and value must be documents */
    ITEM_MERGE = 5;

    /** insert the value in the array at the index identified in the source path */
    ARRAY_INSERT = 6;

    /** append the value on the array at the identified path */
    ARRAY_APPEND = 7;

    /** merge JSON object value with the provided patch expression */
    MERGE_PATCH = 8;
  }

  /** specification of the value to be updated
      - if data_model is TABLE, a column name may be specified and also
        a document path, if the column has type JSON
      - if data_model is DOCUMENT, only document paths are allowed

      @note in both cases, schema and table must be not set */
  required Mysqlx.Expr.ColumnIdentifier source = 1;

  /** the type of operation to be performed */
  required UpdateType operation = 2;

  /** an expression to be computed as the new value for the operation */
  optional Mysqlx.Expr.Expr value = 3;
}

/**
Find Documents/Rows in a Collection/Table

@startuml
  client -> server: Find
  ... one or more Resultset ...
@enduml

@returns @ref Mysqlx::Resultset
*/
message Find {
  enum RowLock {
    /** Lock matching rows against updates */
    SHARED_LOCK = 1;
    /** Lock matching rows so no other transaction can read or write to it */
    EXCLUSIVE_LOCK = 2;
  }

  enum RowLockOptions {
    /** Do not wait to acquire row lock, fail with an error
        if a requested row is locked */
    NOWAIT = 1;
    /** Do not wait to acquire a row lock,
        remove locked rows from the result set */
    SKIP_LOCKED = 2;
  }


  /** collection in which to find */
  required Collection collection = 2;

  /** data model that the operations refer to */
  optional DataModel data_model = 3;

  /** list of column projections that shall be returned */
  repeated Projection projection = 4;

  /** values for parameters used in filter expression */
  repeated Mysqlx.Datatypes.Scalar args = 11;

  /** filter criteria */
  optional Mysqlx.Expr.Expr criteria = 5;

  /** numbers of rows that shall be skipped and returned
      (user can set one of: limit, limit_expr) */
  optional Limit limit = 6;

  /** sort-order in which the rows/document shall be returned in */
  repeated Order order = 7;

  /** column expression list for aggregation (GROUP BY) */
  repeated Mysqlx.Expr.Expr grouping = 8;

  /** filter criteria for aggregated groups */
  optional Mysqlx.Expr.Expr grouping_criteria = 9;

  /** perform row locking on matches */
  optional RowLock locking = 12;

  /** additional options how to handle locked rows */
  optional RowLockOptions locking_options = 13;

  /** numbers of rows that shall be skipped and returned
      (user can set one of: limit, limit_expr) */
  optional LimitExpr limit_expr = 14;

  option (client_message_id) = CRUD_FIND; // comment_out_if PROTOBUF_LITE
}

/**
Insert documents/rows into a collection/table

@returns @ref Mysqlx::Resultset
*/
message Insert {
  /** collection to insert into */
  required Collection collection = 1;

  /** data model that the operations refer to */
  optional DataModel data_model = 2;

  /** name of the columns to insert data into
      (empty if data_model is DOCUMENT) */
  repeated Column projection = 3;

  /** set of fields to insert as a one row */
  message TypedRow {
    repeated Mysqlx.Expr.Expr field = 1;
  }

  /** set of rows to insert into the collection/table (a single expression
      with a JSON document literal or an OBJECT expression) */
  repeated TypedRow row = 4;

  /** values for parameters used in row expressions */
  repeated Mysqlx.Datatypes.Scalar args = 5;

  /** true if this should be treated as an Upsert
      (that is, update on duplicate key) */
  optional bool upsert = 6 [default = false];

  option (client_message_id) = CRUD_INSERT; // comment_out_if PROTOBUF_LITE
}

/**
Update documents/rows in a collection/table

@returns @ref Mysqlx::Resultset
*/
message Update {
  /** collection to change */
  required Collection collection = 2;

  /** datamodel that the operations refer to  */
  optional DataModel data_model = 3;

  /** filter expression to match rows that the operations will apply on */
  optional Mysqlx.Expr.Expr criteria = 4;

  /** limits the number of rows to match
      (user can set one of: limit, limit_expr) */
  optional Limit limit = 5;

  /** specifies order of matched rows */
  repeated Order order = 6;

  /** list of operations to be applied.
      Valid operations will depend on the data_model */
  repeated UpdateOperation operation = 7;

  /** values for parameters used in filter expression */
  repeated Mysqlx.Datatypes.Scalar args = 8;

  /** limits the number of rows to match
      (user can set one of: limit, limit_expr) */
  optional LimitExpr limit_expr = 9;

  option (client_message_id) = CRUD_UPDATE; // comment_out_if PROTOBUF_LITE
}

/**
Delete documents/rows from a Collection/Table

@returns @ref Mysqlx::Resultset
*/
message Delete {
  /** collection to change */
  required Collection collection = 1;

  /** data model that the operations refer to */
  optional DataModel data_model = 2;

  /** filter expression to match rows that the operations will apply on */
  optional Mysqlx.Expr.Expr criteria = 3;

  /** limits the number of rows to match
      (user can set one of: limit, limit_expr) */
  optional Limit limit = 4;

  /** specifies order of matched rows */
  repeated Order order = 5;

  /** values for parameters used in filter expression */
  repeated Mysqlx.Datatypes.Scalar args = 6;

  /** limits the number of rows to match
      (user can set one of: limit, limit_expr) */
  optional LimitExpr limit_expr = 7;

  option (client_message_id) = CRUD_DELETE; // comment_out_if PROTOBUF_LITE
}


/**
ViewAlgorithm defines how MySQL Server processes the view
*/
enum ViewAlgorithm {
  /** MySQL chooses which algorithm to use */
  UNDEFINED =1;

  /** the text of a statement that refers to the view and the view
      definition are merged */
  MERGE = 2;

  /** the view are retrieved into a temporary table */
  TEMPTABLE = 3;
}

/**
ViewSqlSecurity defines the security context in which the view is going to be
executed; this means that VIEW can be executed with current user permissions or
with permissions of the user who defined the VIEW
*/
enum ViewSqlSecurity {
  /** use current user permissions */
  INVOKER = 1;

  /** use permissions of the user who defined the VIEW */
  DEFINER = 2;
}


/**
ViewCheckOption limits the write operations done on a `VIEW`
(`INSERT`, `UPDATE`, `DELETE`) to rows in which the `WHERE` clause is `TRUE`
*/
enum ViewCheckOption {
  /** the view WHERE clause is checked, but no underlying views are checked */
  LOCAL = 1;

  /** the view WHERE clause is checked, then checking recurses
      to underlying views */
  CASCADED = 2;
}


/**
CreateView create view based on indicated @ref Mysqlx::Crud::Find message
*/
message CreateView {
  /** name of the VIEW object, which should be created */
  required Collection collection = 1;

  /** user name of the definer, if the value isn't set then the definer
      is current user */
  optional string definer = 2;

  /** defines how MySQL Server processes the view */
  optional ViewAlgorithm algorithm = 3 [default = UNDEFINED];

  /** defines the security context in which the view is going be executed */
  optional ViewSqlSecurity security = 4 [default = DEFINER];

  /** limits the write operations done on a VIEW */
  optional ViewCheckOption check = 5;

  /** defines the list of aliases for column names specified in `stmt` */
  repeated string column = 6;

  /** Mysqlx.Crud.Find message from which the SELECT statement
      is going to be build */
  required Find stmt = 7;

  /** if true then suppress error when created view already exists;
      just replace it */
  optional bool replace_existing = 8 [default = false];

  option (client_message_id) = CRUD_CREATE_VIEW; // comment_out_if PROTOBUF_LITE
}


/**
ModifyView modify existing view based on indicated
@ref Mysqlx::Crud::Find message
*/
message ModifyView {
  /** name of the VIEW object, which should be modified */
  required Collection collection = 1;

  /** user name of the definer,
      if the value isn't set then the definer is current user */
  optional string definer = 2;

  /** defined how MySQL Server processes the view */
  optional ViewAlgorithm algorithm = 3;

  /** defines the security context in which the view is going be executed */
  optional ViewSqlSecurity security = 4;

  /** limits the write operations done on a VIEW */
  optional ViewCheckOption check = 5;

  /** defines the list of aliases for column names specified in `stmt` */
  repeated string column = 6;

  /** Mysqlx.Crud.Find message from which the SELECT statement
      is going to be build */
  optional Find stmt = 7;

  option (client_message_id) = CRUD_MODIFY_VIEW; // comment_out_if PROTOBUF_LITE
}


/**
DropView removing existing view
*/
message DropView {
  /** name of the VIEW object, which should be deleted */
  required Collection collection = 1;

  /** if true then suppress error when deleted view does not exists */
  optional bool if_exists = 2 [ default = false ];

  option (client_message_id) = CRUD_DROP_VIEW; // comment_out_if PROTOBUF_LITE
}
