package exec.user;

option java_package = "org.apache.drill.exec.proto";
option java_outer_classname = "UserProtos";
option optimize_for = SPEED;

import "SchemaDef.proto";
import "Types.proto";
import "UserBitShared.proto";
import "BitData.proto";
import "BitControl.proto";
import "ExecutionProtos.proto";

////// User <-> Bit RPC ///////
enum RpcType {
  HANDSHAKE = 0;
  ACK = 1;
  GOODBYE = 2;

  // user to bit
  RUN_QUERY = 3; // user is submitting a new query to the drillbit
  CANCEL_QUERY = 4; // user is sending a query cancellation request to the drillbit
  REQUEST_RESULTS = 5;
  RESUME_PAUSED_QUERY = 11; // user is sending a query resume request to the drillbit
  GET_QUERY_PLAN_FRAGMENTS = 12; // to get plan fragments from query
  GET_CATALOGS = 14; // user is requesting metadata of catalog(s).
  GET_SCHEMAS = 15; // user is requesting metadata of schema(s)
  GET_TABLES = 16; // user is requesting metadata of table(s)
  GET_COLUMNS = 17; // user is requesting metadata of column(s)
  CREATE_PREPARED_STATEMENT = 22; // user is sending a request to create prepared statement
  GET_SERVER_META = 8; // user is sending a request to receive server metadata

  // bit to user
  QUERY_DATA = 6; // drillbit is sending a query result data batch to the user
  QUERY_HANDLE = 7;
  QUERY_PLAN_FRAGMENTS = 13; // return plan fragments
  CATALOGS = 18; // return catalogs metadata in response to GET_CATALOGS
  SCHEMAS = 19; // return schema metadata in response to GET_SCHEMAS
  TABLES = 20; // return table metadata in response to GET_TABLES
  COLUMNS = 21; // return column metadata in response to GET_COLUMNS
  PREPARED_STATEMENT = 23; // return preparated statement in response to CREATE_PREPARED_STATEMENT
  SERVER_META = 9; // return server infos in respose to GET_SERVER_META

  QUERY_RESULT = 10; // drillbit is reporting a query status change, most likely a terminal message, to the user

  // user to bit and bit to user
  SASL_MESSAGE = 24;
}

message Property {
  required string key = 1;
  required string value = 2;
}

message UserProperties {
  repeated Property properties = 1;
}

message RpcEndpointInfos {
    optional string name = 1;             // example: Apache Drill Server, Apache Drill C++ client
    optional string version = 2;          // example: 1.9.0
    optional uint32 majorVersion = 3;     // example: 1
    optional uint32 minorVersion = 4;     // example: 9
    optional uint32 patchVersion = 5;     // example: 0
    optional string application = 6;      // example: Tableau 9.3
    optional uint32 buildNumber = 7;      // example: 32
    optional string versionQualifier = 8; // example: SNAPSHOT
}

enum SaslSupport {
  UNKNOWN_SASL_SUPPORT = 0;
  SASL_AUTH = 1;
  SASL_PRIVACY = 2;
}

message UserToBitHandshake {
  optional exec.shared.RpcChannel channel = 1 [default = USER];
  optional bool support_listening = 2;
  optional int32 rpc_version = 3;
  optional exec.shared.UserCredentials credentials = 4;
  optional UserProperties properties = 5;
  optional bool support_complex_types = 6 [default = false];
  optional bool support_timeout = 7 [default = false];
  optional RpcEndpointInfos client_infos = 8;
  optional SaslSupport sasl_support = 9;
}

message RequestResults {
  optional exec.shared.QueryId query_id = 1;
  optional int32 maximum_responses = 2;
}

message GetQueryPlanFragments {
  required string query = 1;
  optional exec.shared.QueryType type = 2;
  optional bool split_plan = 3 [default = false];
}

message QueryPlanFragments {
  required exec.shared.QueryResult.QueryState status = 1;
  optional exec.shared.QueryId query_id = 2;
  repeated exec.bit.control.PlanFragment fragments = 3;
  optional exec.shared.DrillPBError error = 4;
}

enum QueryResultsMode {
  STREAM_FULL = 1; // Server will inform the client regularly on the status of the query. Once the query is completed, service will inform the client as each query chunk is made available.
  // STREAM_FIRST = 2; // Server will inform the client regularly on the status of the query.  Once the query is completed, server will inform the client of the first query chunk.
  // QUERY_FOR_STATUS = 3; // Client will need to query for status of query.
}

enum HandshakeStatus {
  SUCCESS = 1; // Handshake is successful (including authentication if any)
  RPC_VERSION_MISMATCH = 2; // Client and Server RPC versions are different
  AUTH_FAILED = 3; // User authentication failed
  UNKNOWN_FAILURE = 4; // Unknown failure, refer to the error message for more details
  AUTH_REQUIRED = 5; // User authentication required
}

message BitToUserHandshake {
  optional int32 rpc_version = 2;
  optional HandshakeStatus status = 3;
  optional string errorId = 4;
  optional string errorMessage = 5;
  optional RpcEndpointInfos server_infos = 6;
  repeated string authenticationMechanisms = 7;
  repeated RpcType supported_methods = 8;
  optional bool encrypted = 9;
  optional int32 maxWrappedSize = 10;
}

/*
 * Enum indicating the request status.
 */
enum RequestStatus {
  UNKNOWN_STATUS = 0;
  OK = 1;
  FAILED = 2;

  /**
   * Request timed out. Futher attempts can change any API specific parameters and retry or just retry the request.
   */
  TIMEOUT = 3;
}

/*
 * Simple filter which encapsulates the SQL LIKE ... ESCAPE function
 */
message LikeFilter {
  optional string pattern = 1; // pattern to match
  optional string escape = 2; // escape character (if any) present in the pattern
}

/*
 * Request message for getting the metadata for catalogs satisfying the given optional filter.
 */
message GetCatalogsReq {
  optional LikeFilter catalog_name_filter = 1;
}

/*
 * Message encapsulating metadata for a Catalog.
 */
message CatalogMetadata {
  optional string catalog_name = 1;
  optional string description = 2;
  optional string connect = 3;
}

/*
 * Response message for GetCatalogReq.
 */
message GetCatalogsResp {
  optional RequestStatus status = 1;
  repeated CatalogMetadata catalogs = 2;
  optional exec.shared.DrillPBError error = 3;
}

/*
 * Request message for getting the metadata for schemas satisfying the given optional filters.
 */
message GetSchemasReq {
  optional LikeFilter catalog_name_filter = 1;
  optional LikeFilter schema_name_filter = 2;
}

/*
 * Message encapsulating metadata for a Schema.
 */
message SchemaMetadata {
  optional string catalog_name = 1;
  optional string schema_name = 2;
  optional string owner = 3;
  optional string type = 4; // Type. Ex. "file", "mongodb", "hive" etc.
  optional string mutable = 5;
}

/*
 * Response message for GetSchemasReq.
 */
message GetSchemasResp {
  optional RequestStatus status = 1;
  repeated SchemaMetadata schemas = 2;
  optional exec.shared.DrillPBError error = 3;
}

/*
 * Request message for getting the metadata for tables satisfying the given optional filters.
 */
message GetTablesReq {
  optional LikeFilter catalog_name_filter = 1;
  optional LikeFilter schema_name_filter = 2;
  optional LikeFilter table_name_filter = 3;
  repeated string table_type_filter = 4;
}

/*
 * Message encapsulating metadata for a Table.
 */
message TableMetadata {
  optional string catalog_name = 1;
  optional string schema_name = 2;
  optional string table_name = 3;
  optional string type = 4; // Type. Ex. "TABLE", "VIEW" etc.
}

/*
 * Response message for GetTablesReq.
 */
message GetTablesResp {
  optional RequestStatus status = 1;
  repeated TableMetadata tables = 2;
  optional exec.shared.DrillPBError error = 3;
}

/*
 * Request message for getting the metadata for columns satisfying the given optional filters.
 */
message GetColumnsReq {
  optional LikeFilter catalog_name_filter = 1;
  optional LikeFilter schema_name_filter = 2;
  optional LikeFilter table_name_filter = 3;
  optional LikeFilter column_name_filter = 4;
}

/*
 * Message encapsulating metadata for a Column.
 */
message ColumnMetadata {
  optional string catalog_name = 1;
  optional string schema_name = 2;
  optional string table_name = 3;
  optional string column_name = 4;
  optional int32 ordinal_position = 5;
  optional string default_value = 6;
  optional bool is_nullable = 7;
  optional string data_type = 8;
  optional int32 char_max_length = 9;
  optional int32 char_octet_length = 10;
  optional int32 numeric_precision = 11;
  optional int32 numeric_precision_radix = 12;
  optional int32 numeric_scale = 13;
  optional int32 date_time_precision = 14;
  optional string interval_type = 15;
  optional int32 interval_precision = 16;
  optional int32 column_size = 17;
}

/*
 * Response message for GetColumnsReq.
 */
message GetColumnsResp {
  optional RequestStatus status = 1;
  repeated ColumnMetadata columns = 2;
  optional exec.shared.DrillPBError error = 3;
}

/*
 * Request message to create a prepared statement. Currently prepared
 * statement only accepts a SQL query. Query parameter support is not
 * included in current implementation.
 */
message CreatePreparedStatementReq {
  optional string sql_query = 1;
}

/*
 * How a column can be used in WHERE clause
 */
enum ColumnSearchability {
  UNKNOWN_SEARCHABILITY = 0;
  NONE = 1; // can't be used in WHERE clause
  CHAR = 2; // can be used in WHERE clause but only with LIKE predicate
  NUMBER = 3; // can be used in a WHERE clause with all the comparison operators except LIKE
  ALL = 4; // can be used in a WHERE clause with all the comparison operators
}

/*
 * Whether a column can be updatable.
 */
enum ColumnUpdatability {
  UNKNOWN_UPDATABILITY = 0;
  READ_ONLY = 1;
  WRITABLE = 2;
}

/*
 * Metadata of a column in query result set
 */
message ResultColumnMetadata {
  /*
   * Designated column's catalog name. Empty string if not applicable.
   * Defaults to "DRILL" as drill has only one catalog.
   */
  optional string catalog_name = 1;

  /*
   * Designated column's schema name. Not set if not applicable. Initial implementation
   * defaults to no value as we use LIMIT 0 queries to get the schema and schema info
   * is lost. If we derive the schema from plan, we may get the right value.
   */
  optional string schema_name = 2;

  /*
   * Designated column's table name. Not set if not applicable. Initial implementation
   * defaults to no value as we use LIMIT 0 queries to get the schema and table info
   * is lost. If we derive the schema from query plan, we may get the right value.
   */
  optional string table_name = 3;
  optional string column_name = 4; // column name

  /*
   * Column label name for display or print purposes.
   * Ex. a column named "empName" might be labeled as "Employee Name".
   */
  optional string label = 5;

  /*
   * Data type in string format. Value is SQL standard type.
   */
  optional string data_type = 6;

  optional bool is_nullable = 7;

  /*
   * For numeric data, this is the maximum precision.
   * For character data, this is the length in characters.
   * For datetime datatypes, this is the length in characters of the String representation
   *    (assuming the maximum allowed precision of the fractional seconds component).
   * For binary data, this is the length in bytes.
   * For all other types 0 is returned where the column size is not applicable.
   */
  optional int32 precision = 8;

  /*
   * Column's number of digits to right of the decimal point.
   * 0 is returned for types where the scale is not applicable
   */
  optional int32 scale = 9;

  /*
   * Indicates whether values in the designated column are signed numbers.
   */
  optional bool signed = 10;

  /*
   * Maximum number of characters required to display data from the column.
   */
  optional int32 display_size = 11;

  /*
   * Is the column an aliased column. Initial implementation defaults to
   * true as we derive schema from LIMIT 0 query and not the query plan.
   */
  optional bool is_aliased = 12;

  optional ColumnSearchability searchability = 13;

  /*
   * Defaults to READ_ONLY
   */
  optional ColumnUpdatability updatability = 14;

  /*
   * whether the designated column is automatically incremented.
   */
  optional bool auto_increment = 15;

  /*
   * Whether column's case matters for collations and comparisons. Defaults to true.
   */
  optional bool case_sensitivity = 16;

  /*
   * whether the column can be used in ORDER BY clause
   */
  optional bool sortable = 17;

  /*
   * A fully-qualified name of the Java class whose instances are created
   * if the method ResultSet.getObject is called to retrieve
   * a value from the column. Applicable only to JDBC clients.
   */
  optional string class_name = 18;

  /*
   * Is the data type a currency type? For JDBC only.
   */
  optional bool is_currency = 20;
}

/*
 * Server state of prepared statement. Contents are opaque to
 * client. Client just need to submit this object in RunQuery to
 * the prepared statement.
 */
message PreparedStatementHandle {
  optional bytes server_info = 1;
}

/*
 * Prepared statement. It contains the query metadata and handle to prepared
 * statement state on server.
 */
message PreparedStatement {
  repeated ResultColumnMetadata columns = 1;

  /*
   * In order to execute the prepared statement,
   * clients need to submit this object in RunQuery message.
   */
  optional PreparedStatementHandle server_handle = 2;
}

/*
 * Response message for CreatePreparedStatementReq.
 */
message CreatePreparedStatementResp {
  optional RequestStatus status = 1;
  optional PreparedStatement prepared_statement = 2;
  optional exec.shared.DrillPBError error = 3;
}

/*
 * Request message for getting server metadata
 */
message GetServerMetaReq {
}

enum CollateSupport {
    CS_UNKNOWN      = 0;   // Unknown support (for forward compatibility)
    CS_GROUP_BY     = 1;   // COLLATE clause can be added after each grouping column
}
message ConvertSupport {
  required common.MinorType from = 1;
  required common.MinorType to = 2;
}

enum CorrelationNamesSupport {
    CN_NONE = 1;               // Correlation names are not supported
    CN_DIFFERENT_NAMES = 2;    // Correlation names are supported, but names have to
                               // be different from the tables they represent
    CN_ANY = 3;                // Correlation names are supported without restriction
}

enum DateTimeLiteralsSupport {
    DL_UNKNOWN = 0;                    // Unknown support (for forward compatibility)
    DL_DATE = 1;                       // DATE literal is supported
    DL_TIME = 2;                       // TIME literal is supported
    DL_TIMESTAMP = 3;                  // TIMESTAMP literal is supported
    DL_INTERVAL_YEAR = 4;              // INTERVAL YEAR literal is supported
    DL_INTERVAL_MONTH = 5;             // INTERVAL MONTH literal is supported
    DL_INTERVAL_DAY = 6;               // INTERVAL DAY literal is supported
    DL_INTERVAL_HOUR = 7;              // INTERVAL HOUR literal is supported
    DL_INTERVAL_MINUTE = 8;            // INTERVAL MINUTE literal is supported
    DL_INTERVAL_SECOND = 9;            // INTERVAL SECOND literal is supported
    DL_INTERVAL_YEAR_TO_MONTH = 10;    // INTERVAL YEAR TO MONTH literal is supported
    DL_INTERVAL_DAY_TO_HOUR = 11;      // INTERVAL DAY TO HOUR literal is supported
    DL_INTERVAL_DAY_TO_MINUTE = 12;    // INTERVAL DAY TO MINUTE literal is supported
    DL_INTERVAL_DAY_TO_SECOND = 13;    // INTERVAL DAY TO SECOND literal is supported
    DL_INTERVAL_HOUR_TO_MINUTE = 14;   // INTERVAL HOUR TO MINUTE literal is supported
    DL_INTERVAL_HOUR_TO_SECOND = 15;   // INTERVAL HOUR TO SECOND literal is supported
    DL_INTERVAL_MINUTE_TO_SECOND = 16; // INTERVAL MINUTE TO SECOND literal is supported
}

enum GroupBySupport {
    GB_NONE = 1;           // Group by is not supported
    GB_SELECT_ONLY = 2;    // Group by supported with non aggregated columns in select
    GB_BEYOND_SELECT = 3;  /* Group by supported with columns absent from the select list
                              if all the non-aggregated colums from the select list are also added */
    GB_UNRELATED = 4;      // Group by supported with columns absent from the select list
}

enum IdentifierCasing {
    IC_UNKNOWN = 0;        // Unknown support (for forward compatibility)
    IC_STORES_LOWER = 1;   /* Mixed case identifier is treated as case insensitive
                              and stored in lower case */
    IC_STORES_MIXED = 2;   /* Mixed case identifier is treated as case insensitive
                              and stored in mixed case */
    IC_STORES_UPPER = 3;   /* Mixed case identifier is treated as case insensitive
                              and stored in upper case */
    IC_SUPPORTS_MIXED = 4; /* Mixed case identifier is treated as case sensitive
                              and stored in mixed case */
}

enum NullCollation {
    NC_UNKNOWN   = 0;  // Unknown support (for forward compatibility)
    NC_AT_START  = 1;  // NULL values are sorted at the start regardless of the order
    NC_AT_END = 2;     // NULL values are sorted at the end regardless of the order
    NC_HIGH = 3;       // NULL is the highest value
    NC_LOW = 4;        // NULL is the lowest value
}

enum OrderBySupport {
    OB_UNKNOWN = 0;     // Unknown support (for forward compatibility)
    OB_UNRELATED = 1;   // ORDER BY supported with columns not in SELECT list
    OB_EXPRESSION = 2;  // ORDER BY with expressions is supported
}

enum OuterJoinSupport {
    OJ_UNKNOWN = 0;            // Unknown support (for forward compatibility)
    OJ_LEFT = 1;               // Left outer join is supported
    OJ_RIGHT = 2;              // Right outer join is supported
    OJ_FULL = 3;               // Full outer join is supported
    OJ_NESTED = 4;             // Nested outer join is supported
    OJ_NOT_ORDERED = 5;        /* Column names in the ON clause don't have to share the same order
                                  as their respective table names in the OUTER JOIN clase */
    OJ_INNER = 6;              // Inner table can also be used in an inner join
    OJ_ALL_COMPARISON_OPS = 7; // Any comparison operator is supported in the ON clause
}

enum SubQuerySupport {
    SQ_UNKNOWN    = 0;     // Unknown support (for forward compatibility)
    SQ_CORRELATED = 1;     // Correlated subquery is supported
    SQ_IN_COMPARISON = 2;  // Subquery in comparison expression is supported
    SQ_IN_EXISTS = 3;      // Subquery in EXISTS expression is supported
    SQ_IN_INSERT = 4;      // Subquery in INSERT expression is supported
    SQ_IN_QUANTIFIED = 5;  // Subquery in quantified expression is supported
}

enum UnionSupport {
    U_UNKNOWN = 0;    // Unknown support (for forward compatibility)
    U_UNION = 1;      // UNION is supported
    U_UNION_ALL = 2;  // UNION_ALL is supported
}

/*
 * Response message for GetServerMetaReq
 */
message GetServerMetaResp {
  optional RequestStatus status = 1;
  optional ServerMeta server_meta = 2;
  optional exec.shared.DrillPBError error = 3;
}

message ServerMeta {
    // True if current user can use all tables returned by GetTables
    optional bool                       all_tables_selectable = 1;
    // True if BLOB are included into the max row size
    optional bool                       blob_included_in_max_row_size = 2;
    // True if catalog name is at the start of a fully qualified table
    optional bool                       catalog_at_start = 3;
    // The catalog separator
    optional string                     catalog_separator = 4;
    // The term used to designate catalogs
    optional string                     catalog_term = 5;
    // COLLATE support
    repeated CollateSupport             collate_support = 6;
    // True if column aliasing is supported
    optional bool                       column_aliasing_supported = 7;
    // CONVERT support
    repeated ConvertSupport             convert_support = 8;
    // Correlation names support
    optional CorrelationNamesSupport    correlation_names_support = 9;
    // Supported ODBC/JDBC Date Time scalar functions
    repeated string                     date_time_functions = 10;
    // Supported Date Time literals
    repeated DateTimeLiteralsSupport    date_time_literals_support = 11;
    // Group By support
    optional GroupBySupport             group_by_support = 12;
    // Unquoted Identifier casing
    optional IdentifierCasing           identifier_casing = 13;
    // Quote string for identifiers
    optional string                     identifier_quote_string = 14;
    // True if LIKE supports an ESCAPE clause
    optional bool                       like_escape_clause_supported = 15;
    // Maximum number of hexa characters for binary literals (0 if unlimited or unknown)
    optional uint32                     max_binary_literal_length = 16;
    // Maximum length of catalog names (0 if unlimited or unknown)
    optional uint32                     max_catalog_name_length = 17;
    // Maximum number of characters for string literals (0 if unlimited or unknown)
    optional uint32                     max_char_literal_length = 18;
    // Maximum length of column names (0 if unlimited or unknown)
    optional uint32                     max_column_name_length = 19;
    // Maximum number of columns in GROUP BY expressions (0 if unlimited or unknown)
    optional uint32                     max_columns_in_group_by = 20;
    // Maximum number of columns in ORDER BY expressions (0 if unlimited or unknown)
    optional uint32                     max_columns_in_order_by = 21;
    // Maximum number of columns in SELECT expressions (0 if unlimited or unknown)
    optional uint32                     max_columns_in_select = 22;
    // Maximum length of cursor names (0 if unlimited or unknown)
    optional uint32                     max_cursor_name_length = 23;
    // Maximum logical size for LOB types (0 if unlimited or unknown)
    optional uint32                     max_logical_lob_size = 24;
    // Maximum number of bytes for a single row (0 if unlimited or unknown)
    optional uint32                     max_row_size = 25;
    // Maximum length of schema names (0 if unlimited or unknown)
    optional uint32                     max_schema_name_length = 26;
    // Maximum length for statements (0 if unlimited or unknown)
    optional uint32                     max_statement_length = 27;
    // Maximum number of statements (0 if unlimited or unknown)
    optional uint32                     max_statements = 28;
    // Maximum length of table names (0 if unlimited or unknown)
    optional uint32                     max_table_name_length = 29;
    // Maximum number of tables in a SELECT expression (0 if unlimited or unknown)
    optional uint32                     max_tables_in_select = 30;
    // Maximum length of user names (0 if unlimited or unknown)
    optional uint32                     max_user_name_length = 31;
    // How NULL are sorted
    optional NullCollation              null_collation = 32;
    // True if NULL + non NULL is NULL
    optional bool                       null_plus_non_null_equals_null = 33;
    // Supported ODBC/JDBC numeric scalar functions
    repeated string                     numeric_functions = 34;
    // Outer join suport
    repeated OrderBySupport             order_by_support = 35;
    // Outer join suport
    repeated OuterJoinSupport           outer_join_support = 36;
    // Quoted identifier casing
    optional IdentifierCasing           quoted_identifier_casing = 37;
    // True if connection access is read only
    optional bool                       read_only = 38;
    // The term used to designate a schema
    optional string                     schema_term = 39;
    // Characters used for escaping (empty if not suported)
    optional string                     search_escape_string = 40;
    // True if SELECT FOR UPDATE is supported
    optional bool                       select_for_update_supported = 41;
    // List of extra characters that can be used in identifier names
    optional string                     special_characters = 42;
    // list of SQL keywords
    repeated string                     sql_keywords = 43;
    // Supported ODBC/JDBC string scalar functions
    repeated string                     string_functions = 44;
    // Subquery support
    repeated SubQuerySupport            subquery_support = 45;
    // Supported ODBC/JDBC systen scalar functions
    repeated string                     system_functions = 46;
    // The term used to designate a table
    optional string                     table_term = 47;
    // True if transaction is supported
    optional bool                       transaction_supported = 48;
    // UNION support
    repeated UnionSupport               union_support = 49;
}

/*
 * Request message for running a query.
 */
message RunQuery {
  optional QueryResultsMode results_mode = 1;
  optional exec.shared.QueryType type = 2;

  /*
   * Input for query type LOGICAL, PHYSICAL or SQL.
   */
  optional string plan = 3;

  /*
   * Input for query type EXECUTION. Input is a set of executable fragments.
   */
  repeated exec.bit.control.PlanFragment fragments = 4;

  /*
   * Input for query type PREPARED_STATEMENT. Input is a prepared statement handle
   * to state on server side which is returned in response to CreatePreparedStatementReq.
   */
  optional PreparedStatementHandle prepared_statement_handle = 5;
}
