#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[skip_serializing_none]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Aggregate")]
pub enum Aggregate {
ColumnCount {
/// The column to apply the count aggregate function to
column: FieldName,
/// Arguments to satisfy the column specified by 'column'
#[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
arguments: BTreeMap<ArgumentName, Argument>,
/// Path to a nested field within an object column
field_path: Option<Vec<FieldName>>,
/// Whether or not only distinct items should be counted
distinct: bool,
},
SingleColumn {
/// The column to apply the aggregation function to
column: FieldName,
/// Arguments to satisfy the column specified by 'column'
#[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
arguments: BTreeMap<ArgumentName, Argument>,
/// Path to a nested field within an object column
field_path: Option<Vec<FieldName>>,
/// Single column aggregate function name.
function: AggregateFunctionName,
},
StarCount {},
}
#[skip_serializing_none]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Aggregate Capabilities")]
pub struct AggregateCapabilities {
/// Does the connector support filtering based on aggregated values
pub filter_by: Option<LeafCapability>,
/// Does the connector support aggregations over groups
pub group_by: Option<GroupByCapabilities>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Aggregate Capabilities Schema Info")]
pub struct AggregateCapabilitiesSchemaInfo {
/// The scalar type which should be used for the return type of count
/// (star_count and column_count) operations.
pub count_scalar_type: ScalarTypeName,
}
/// The definition of an aggregation function on a scalar type
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Aggregate Function Definition")]
pub enum AggregateFunctionDefinition {
Min,
Max,
Sum {
/// The scalar type of the result of this function, which should have
/// one of the type representations Int64 or Float64, depending on
/// whether this function is defined on a scalar type with an integer or
/// floating-point representation, respectively.
result_type: ScalarTypeName,
},
Average {
/// The scalar type of the result of this function, which should have
/// the type representation Float64
result_type: ScalarTypeName,
},
Custom {
/// The scalar or object type of the result of this function
result_type: Type,
},
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Argument")]
pub enum Argument {
/// The argument is provided by reference to a variable.
/// Only used if the 'query.variables' capability is supported.
Variable { name: VariableName },
/// The argument is provided as a literal value
Literal { value: serde_json::Value },
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Argument Info")]
pub struct ArgumentInfo {
/// Argument description
pub description: Option<String>,
/// The name of the type of this argument
#[serde(rename = "type")]
pub argument_type: Type,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Array Comparison")]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ArrayComparison {
/// Check if the array contains the specified value.
/// Only used if the 'query.nested_fields.filter_by.nested_arrays.contains' capability is supported.
Contains { value: ComparisonValue },
/// Check is the array is empty.
/// Only used if the 'query.nested_fields.filter_by.nested_arrays.is_empty' capability is supported.
IsEmpty,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Capabilities Response")]
pub struct CapabilitiesResponse {
pub version: String,
pub capabilities: Capabilities,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Capability Schema Info")]
pub struct CapabilitySchemaInfo {
/// Schema information relevant to query capabilities
pub query: Option<QueryCapabilitiesSchemaInfo>,
}
/// The definition of a comparison operator on a scalar type
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Comparison Operator Definition")]
pub enum ComparisonOperatorDefinition {
Equal,
In,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual,
Contains,
ContainsInsensitive,
StartsWith,
StartsWithInsensitive,
EndsWith,
EndsWithInsensitive,
Custom {
/// The type of the argument to this operator
argument_type: Type,
},
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Comparison Target")]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ComparisonTarget {
/// The comparison targets a column.
Column {
/// The name of the column
name: FieldName,
/// Arguments to satisfy the column specified by 'name'
#[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
arguments: BTreeMap<ArgumentName, Argument>,
/// Path to a nested field within an object column.
/// Only non-empty if the 'query.nested_fields.filter_by' capability is supported.
field_path: Option<Vec<FieldName>>,
},
/// The comparison targets the result of aggregation.
/// Only used if the 'query.aggregates.filter_by' capability is supported.
Aggregate {
/// Non-empty collection of relationships to traverse
path: Vec<PathElement>,
/// The aggregation method to use
aggregate: Aggregate,
},
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Comparison Value")]
pub enum ComparisonValue {
/// The value to compare against should be drawn from another column
Column {
/// Any relationships to traverse to reach this column.
/// Only non-empty if the 'relationships.relation_comparisons' is supported.
path: Vec<PathElement>,
/// The name of the column
name: FieldName,
/// Arguments to satisfy the column specified by 'name'
#[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
arguments: BTreeMap<ArgumentName, Argument>,
/// Path to a nested field within an object column.
/// Only non-empty if the 'query.nested_fields.filter_by' capability is supported.
field_path: Option<Vec<FieldName>>,
/// The scope in which this column exists, identified
/// by an top-down index into the stack of scopes.
/// The stack grows inside each `Expression::Exists`,
/// so scope 0 (the default) refers to the current collection,
/// and each subsequent index refers to the collection outside
/// its predecessor's immediately enclosing `Expression::Exists`
/// expression.
/// Only used if the 'query.exists.named_scopes' capability is supported.
scope: Option<usize>,
},
/// A scalar value to compare against
Scalar { value: serde_json::Value },
/// A value to compare against that is to be drawn from the query's variables.
/// Only used if the 'query.variables' capability is supported.
Variable { name: VariableName },
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[skip_serializing_none]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Dimension")]
pub enum Dimension {
Column {
/// Any (object) relationships to traverse to reach this column.
/// Only non-empty if the 'relationships' capability is supported.
path: Vec<PathElement>,
/// The name of the column
column_name: FieldName,
/// Arguments to satisfy the column specified by 'column_name'
#[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
arguments: BTreeMap<ArgumentName, Argument>,
/// Path to a nested field within an object column
field_path: Option<Vec<FieldName>>,
/// The name of the extraction function to apply to the selected value, if any
extraction: Option<ExtractionFunctionName>,
},
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Error Response")]
pub struct ErrorResponse {
/// A human-readable summary of the error
pub message: String,
/// Any additional structured information about the error
pub details: serde_json::Value,
}
#[skip_serializing_none]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Exists Capabilities")]
pub struct ExistsCapabilities {
/// Does the connector support named scopes in column references inside
/// EXISTS predicates
pub named_scopes: Option<LeafCapability>,
/// Does the connector support ExistsInCollection::Unrelated
pub unrelated: Option<LeafCapability>,
/// Does the connector support ExistsInCollection::NestedCollection
pub nested_collections: Option<LeafCapability>,
/// Does the connector support filtering over nested scalar arrays using existential quantification.
/// This means the connector must support ExistsInCollection::NestedScalarCollection.
pub nested_scalar_collections: Option<LeafCapability>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Exists In Collection")]
pub enum ExistsInCollection {
/// The rows to evaluate the exists predicate against come from a related collection.
/// Only used if the 'relationships' capability is supported.
Related {
#[serde(skip_serializing_if = "Option::is_none", default)]
/// Path to a nested field within an object column that must be navigated
/// before the relationship is navigated.
/// Only non-empty if the 'relationships.nested.filtering' capability is supported.
field_path: Option<Vec<FieldName>>,
/// The name of the relationship to follow
relationship: RelationshipName,
/// Values to be provided to any collection arguments
arguments: BTreeMap<ArgumentName, RelationshipArgument>,
},
/// The rows to evaluate the exists predicate against come from an unrelated collection
/// Only used if the 'query.exists.unrelated' capability is supported.
Unrelated {
/// The name of a collection
collection: CollectionName,
/// Values to be provided to any collection arguments
arguments: BTreeMap<ArgumentName, RelationshipArgument>,
},
/// The rows to evaluate the exists predicate against come from a nested array field.
/// Only used if the 'query.exists.nested_collections' capability is supported.
NestedCollection {
column_name: FieldName,
#[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
arguments: BTreeMap<ArgumentName, Argument>,
/// Path to a nested collection via object columns
#[serde(skip_serializing_if = "Vec::is_empty", default)]
field_path: Vec<FieldName>,
},
/// Specifies a column that contains a nested array of scalars. The
/// array will be brought into scope of the nested expression where
/// each element becomes an object with one '__value' column that
/// contains the element value.
/// Only used if the 'query.exists.nested_scalar_collections' capability is supported.
NestedScalarCollection {
column_name: FieldName,
#[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
arguments: BTreeMap<ArgumentName, Argument>,
/// Path to a nested collection via object columns
#[serde(skip_serializing_if = "Vec::is_empty", default)]
field_path: Vec<FieldName>,
},
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Explain Response")]
pub struct ExplainResponse {
/// A list of human-readable key-value pairs describing
/// a query execution plan. For example, a connector for
/// a relational database might return the generated SQL
/// and/or the output of the `EXPLAIN` command. An API-based
/// connector might encode a list of statically-known API
/// calls which would be made.
pub details: BTreeMap<String, String>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Expression")]
pub enum Expression {
And {
expressions: Vec<Expression>,
},
Or {
expressions: Vec<Expression>,
},
Not {
expression: Box<Expression>,
},
UnaryComparisonOperator {
column: ComparisonTarget,
operator: UnaryComparisonOperator,
},
BinaryComparisonOperator {
column: ComparisonTarget,
operator: ComparisonOperatorName,
value: ComparisonValue,
},
/// A comparison against a nested array column.
/// Only used if the 'query.nested_fields.filter_by.nested_arrays' capability is supported.
ArrayComparison {
column: ComparisonTarget,
comparison: ArrayComparison,
},
Exists {
in_collection: ExistsInCollection,
predicate: Option<Box<Expression>>,
},
}
/// The definition of an aggregation function on a scalar type
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Extraction Function Definition")]
pub enum ExtractionFunctionDefinition {
Nanosecond {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
Microsecond {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
Second {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
Minute {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
Hour {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
Day {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
Week {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
Month {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
Quarter {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
Year {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
DayOfWeek {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
DayOfYear {
/// The result type, which must be a defined scalar type in the schema response.
result_type: ScalarTypeName,
},
Custom {
/// The scalar or object type of the result of this function
result_type: Type,
},
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Field")]
pub enum Field {
/// A field satisfied by returning the value of a row's column.
Column {
column: FieldName,
/// When the type of the column is a (possibly-nullable) array or object,
/// the caller can request a subset of the complete column data,
/// by specifying fields to fetch here.
/// If omitted, the column data will be fetched in full.
fields: Option<NestedField>,
#[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
arguments: BTreeMap<ArgumentName, Argument>,
},
/// A field satisfied by navigating a relationship from the current row to a related collection.
/// Only used if the 'relationships' capability is supported.
Relationship {
query: Box<Query>,
/// The name of the relationship to follow for the subquery
relationship: RelationshipName,
/// Values to be provided to any collection arguments
arguments: BTreeMap<ArgumentName, RelationshipArgument>,
},
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Foreign Key Constraint")]
pub struct ForeignKeyConstraint {
/// The columns on which you want want to define the foreign key.
/// This is a mapping between fields on object type to columns on the foreign collection.
/// The column on the foreign collection is specified via a field path (ie. an array of field
/// names that descend through nested object fields). The field path must only contain a single item,
/// meaning a column on the foreign collection's type, unless the 'relationships.nested'
/// capability is supported, in which case multiple items can be used to denote a nested object field.
pub column_mapping: BTreeMap<FieldName, Vec<FieldName>>,
/// The name of a collection
pub foreign_collection: CollectionName,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Function Info")]
pub struct FunctionInfo {
/// The name of the function
pub name: FunctionName,
/// Description of the function
pub description: Option<String>,
/// Any arguments that this collection requires
pub arguments: BTreeMap<ArgumentName, ArgumentInfo>,
/// The name of the function's result type
pub result_type: Type,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Group")]
pub struct Group {
/// Values of dimensions which identify this group
pub dimensions: Vec<serde_json::Value>,
/// Aggregates computed within this group
pub aggregates: IndexMap<FieldName, serde_json::Value>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Aggregate Comparison Target")]
pub enum GroupComparisonTarget {
Aggregate { aggregate: Aggregate },
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Aggregate Comparison Value")]
pub enum GroupComparisonValue {
/// A scalar value to compare against
Scalar { value: serde_json::Value },
/// A value to compare against that is to be drawn from the query's variables.
/// Only used if the 'query.variables' capability is supported.
Variable { name: VariableName },
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Group Expression")]
pub enum GroupExpression {
And {
expressions: Vec<GroupExpression>,
},
Or {
expressions: Vec<GroupExpression>,
},
Not {
expression: Box<GroupExpression>,
},
UnaryComparisonOperator {
target: GroupComparisonTarget,
operator: UnaryComparisonOperator,
},
BinaryComparisonOperator {
target: GroupComparisonTarget,
operator: ComparisonOperatorName,
value: GroupComparisonValue,
},
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Grouping")]
pub struct Grouping {
/// Dimensions along which to partition the data
pub dimensions: Vec<Dimension>,
/// Aggregates to compute in each group
pub aggregates: IndexMap<FieldName, Aggregate>,
/// Optionally specify a predicate to apply after grouping rows.
/// Only used if the 'query.aggregates.group_by.filter' capability is supported.
pub predicate: Option<GroupExpression>,
/// Optionally specify how groups should be ordered
/// Only used if the 'query.aggregates.group_by.order' capability is supported.
pub order_by: Option<GroupOrderBy>,
/// Optionally limit to N groups
/// Only used if the 'query.aggregates.group_by.paginate' capability is supported.
pub limit: Option<u32>,
/// Optionally offset from the Nth group
/// Only used if the 'query.aggregates.group_by.paginate' capability is supported.
pub offset: Option<u32>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Group By Capabilities")]
pub struct GroupByCapabilities {
/// Does the connector support post-grouping predicates
pub filter: Option<LeafCapability>,
/// Does the connector support post-grouping ordering
pub order: Option<LeafCapability>,
/// Does the connector support post-grouping pagination
pub paginate: Option<LeafCapability>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Group Order By")]
pub struct GroupOrderBy {
/// The elements to order by, in priority order
pub elements: Vec<GroupOrderByElement>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Group Order By Element")]
pub struct GroupOrderByElement {
pub order_direction: OrderDirection,
pub target: GroupOrderByTarget,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Group Order By Target")]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum GroupOrderByTarget {
Dimension {
/// The index of the dimension to order by, selected from the
/// dimensions provided in the `Grouping` request.
index: usize,
},
Aggregate {
/// Aggregation method to apply
aggregate: Aggregate,
},
}
/// A unit value to indicate a particular leaf capability is supported.
/// This is an empty struct to allow for future sub-capabilities.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct LeafCapability {}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Mutation Capabilities")]
pub struct MutationCapabilities {
/// Does the connector support executing multiple mutations in a transaction.
pub transactional: Option<LeafCapability>,
/// Does the connector support explaining mutations
pub explain: Option<LeafCapability>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Mutation Operation")]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum MutationOperation {
Procedure {
/// The name of a procedure
name: ProcedureName,
/// Any named procedure arguments
arguments: BTreeMap<ArgumentName, serde_json::Value>,
/// The fields to return from the result, or null to return everything
fields: Option<NestedField>,
},
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Mutation Operation Results")]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum MutationOperationResults {
Procedure { result: serde_json::Value },
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Mutation Request")]
pub struct MutationRequest {
/// The mutation operations to perform
pub operations: Vec<MutationOperation>,
/// The relationships between collections involved in the entire mutation request.
/// Only used if the 'relationships' capability is supported.
pub collection_relationships: BTreeMap<RelationshipName, Relationship>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Mutation Response")]
pub struct MutationResponse {
/// The results of each mutation operation, in the same order as they were received
pub operation_results: Vec<MutationOperationResults>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(title = "NestedArray")]
pub struct NestedArray {
pub fields: Box<NestedField>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Nested Array Filter By Capabilities")]
pub struct NestedArrayFilterByCapabilities {
/// Does the connector support filtering over nested arrays by checking if the array contains a value.
/// This must be supported for all types that can be contained in an array that implement an 'eq'
/// comparison operator.
pub contains: Option<LeafCapability>,
/// Does the connector support filtering over nested arrays by checking if the array is empty.
/// This must be supported no matter what type is contained in the array.
pub is_empty: Option<LeafCapability>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(title = "NestedCollection")]
pub struct NestedCollection {
pub query: Query,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "NestedField")]
pub enum NestedField {
Object(NestedObject),
Array(NestedArray),
/// Perform a query over the nested array's rows.
/// Only used if the 'query.nested_fields.nested_collections' capability is supported.
Collection(NestedCollection),
}
#[skip_serializing_none]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Nested Field Capabilities")]
pub struct NestedFieldCapabilities {
/// Does the connector support filtering by values of nested fields
pub filter_by: Option<NestedFieldFilterByCapabilities>,
/// Does the connector support ordering by values of nested fields
pub order_by: Option<LeafCapability>,
/// Does the connector support aggregating values within nested fields
pub aggregates: Option<LeafCapability>,
/// Does the connector support nested collection queries using
/// `NestedField::NestedCollection`
pub nested_collections: Option<LeafCapability>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Nested Field Filter By Capabilities")]
pub struct NestedFieldFilterByCapabilities {
/// Does the connector support filtering over nested arrays (ie. Expression::ArrayComparison)
pub nested_arrays: Option<NestedArrayFilterByCapabilities>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(title = "NestedObject")]
pub struct NestedObject {
pub fields: IndexMap<FieldName, Field>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Nested Relationship Capabilities")]
pub struct NestedRelationshipCapabilities {
/// Does the connector support navigating a relationship from inside a nested object inside a nested array
pub array: Option<LeafCapability>,
/// Does the connector support filtering over a relationship that starts from inside a nested object
pub filtering: Option<LeafCapability>,
/// Does the connector support ordering over a relationship that starts from inside a nested object
pub ordering: Option<LeafCapability>,
}
/// The definition of an object field
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Object Field")]
pub struct ObjectField {
/// Description of this field
pub description: Option<String>,
/// The type of this field
#[serde(rename = "type")]
pub r#type: Type,
/// The arguments available to the field - Matches implementation from CollectionInfo
#[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
pub arguments: BTreeMap<ArgumentName, ArgumentInfo>,
}
/// The definition of an object type
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Object Type")]
pub struct ObjectType {
/// Description of this type
pub description: Option<String>,
/// Fields defined on this object type
pub fields: BTreeMap<FieldName, ObjectField>,
/// Any foreign keys defined for this object type's columns
pub foreign_keys: BTreeMap<String, ForeignKeyConstraint>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Order By")]
pub struct OrderBy {
/// The elements to order by, in priority order
pub elements: Vec<OrderByElement>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Order By Element")]
pub struct OrderByElement {
pub order_direction: OrderDirection,
pub target: OrderByTarget,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Order By Target")]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum OrderByTarget {
/// The ordering is performed over a column.
Column {
/// Any (object) relationships to traverse to reach this column.
/// Only non-empty if the 'relationships' capability is supported.
/// 'PathElement.field_path' will only be non-empty if the 'relationships.nested.ordering' capability is supported.
path: Vec<PathElement>,
/// The name of the column
name: FieldName,
/// Arguments to satisfy the column specified by 'name'
#[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
arguments: BTreeMap<ArgumentName, Argument>,
/// Path to a nested field within an object column.
/// Only non-empty if the 'query.nested_fields.order_by' capability is supported.
field_path: Option<Vec<FieldName>>,
},
/// The ordering is performed over the result of an aggregation.
/// Only used if the 'relationships.order_by_aggregate' capability is supported.
Aggregate {
/// Non-empty collection of relationships to traverse.
/// Only non-empty if the 'relationships' capability is supported.
/// 'PathElement.field_path' will only be non-empty if the 'relationships.nested.ordering' capability is supported.
path: Vec<PathElement>,
/// The aggregation method to use
aggregate: Aggregate,
},
}
#[derive(
Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, JsonSchema,
)]
#[schemars(title = "Order Direction")]
#[serde(rename_all = "snake_case")]
pub enum OrderDirection {
Asc,
Desc,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(title = "Path Element")]
pub struct PathElement {
#[serde(skip_serializing_if = "Option::is_none", default)]
/// Path to a nested field within an object column that must be navigated
/// before the relationship is navigated.
/// Only non-empty if the 'relationships.nested' capability is supported
/// (plus perhaps one of the sub-capabilities, depending on the feature using the PathElement).
pub field_path: Option<Vec<FieldName>>,
/// The name of the relationship to follow
pub relationship: RelationshipName,
/// Values to be provided to any collection arguments
pub arguments: BTreeMap<ArgumentName, RelationshipArgument>,
/// A predicate expression to apply to the target collection
pub predicate: Option<Box<Expression>>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Procedure Info")]
pub struct ProcedureInfo {
/// The name of the procedure
pub name: ProcedureName,
/// Column description
pub description: Option<String>,
/// Any arguments that this collection requires
pub arguments: BTreeMap<ArgumentName, ArgumentInfo>,
/// The name of the result type
pub result_type: Type,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Query")]
pub struct Query {
/// Aggregate fields of the query.
/// Only used if the 'query.aggregates' capability is supported.
pub aggregates: Option<IndexMap<FieldName, Aggregate>>,
/// Fields of the query
pub fields: Option<IndexMap<FieldName, Field>>,
/// Optionally limit to N results
pub limit: Option<u32>,
/// Optionally offset from the Nth result
pub offset: Option<u32>,
/// Optionally specify how rows should be ordered
pub order_by: Option<OrderBy>,
/// Optionally specify a predicate to apply to the rows
pub predicate: Option<Expression>,
/// Optionally group and aggregate the selected rows.
/// Only used if the 'query.aggregates.group_by' capability is supported.
pub groups: Option<Grouping>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Query Capabilities")]
pub struct QueryCapabilities {
/// Does the connector support aggregate queries
pub aggregates: Option<AggregateCapabilities>,
/// Does the connector support queries which use variables
pub variables: Option<LeafCapability>,
/// Does the connector support explaining queries
pub explain: Option<LeafCapability>,
/// Does the connector support nested fields
#[serde(default)]
pub nested_fields: NestedFieldCapabilities,
/// Does the connector support EXISTS predicates
#[serde(default)]
pub exists: ExistsCapabilities,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Query Capabilities Schema Info")]
pub struct QueryCapabilitiesSchemaInfo {
/// Schema information relevant to aggregate query capabilities
pub aggregates: Option<AggregateCapabilitiesSchemaInfo>,
}
/// This is the request body of the query POST endpoint
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Query Request")]
pub struct QueryRequest {
/// The name of a collection
pub collection: CollectionName,
/// The query syntax tree
pub query: Query,
/// Values to be provided to any collection arguments
pub arguments: BTreeMap<ArgumentName, Argument>,
/// Any relationships between collections involved in the query request.
/// Only used if the 'relationships' capability is supported.
pub collection_relationships: BTreeMap<RelationshipName, Relationship>,
/// One set of named variables for each rowset to fetch. Each variable set
/// should be subtituted in turn, and a fresh set of rows returned.
/// Only used if the 'query.variables' capability is supported.
pub variables: Option<Vec<BTreeMap<VariableName, serde_json::Value>>>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Query Response")]
/// Query responses may return multiple RowSets when using queries with variables.
/// Else, there should always be exactly one RowSet
pub struct QueryResponse(pub Vec<RowSet>);
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Relationship")]
pub struct Relationship {
/// A mapping between columns on the source row to columns on the target collection.
/// The column on the target collection is specified via a field path (ie. an array of field
/// names that descend through nested object fields). The field path will only contain a single item,
/// meaning a column on the target collection's type, unless the 'relationships.nested'
/// capability is supported, in which case multiple items denotes a nested object field.
pub column_mapping: BTreeMap<FieldName, Vec<FieldName>>,
pub relationship_type: RelationshipType,
/// The name of a collection
pub target_collection: CollectionName,
/// Values to be provided to any collection arguments
pub arguments: BTreeMap<ArgumentName, RelationshipArgument>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Relationship Argument")]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum RelationshipArgument {
/// The argument is provided by reference to a variable.
/// Only used if the 'query.variables' capability is supported.
Variable {
name: VariableName,
},
/// The argument is provided as a literal value
Literal {
value: serde_json::Value,
},
// The argument is provided based on a column of the source collection
Column {
name: FieldName,
},
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Relationship Capabilities")]
pub struct RelationshipCapabilities {
/// Does the connector support comparisons that involve related collections (ie. joins)?
pub relation_comparisons: Option<LeafCapability>,
/// Does the connector support ordering by an aggregated array relationship?
pub order_by_aggregate: Option<LeafCapability>,
/// Does the connector support navigating a relationship from inside a nested object
pub nested: Option<NestedRelationshipCapabilities>,
}
#[derive(
Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, JsonSchema,
)]
#[schemars(title = "Relationship Type")]
#[serde(rename_all = "snake_case")]
pub enum RelationshipType {
Object,
Array,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Row Field Value")]
pub struct RowFieldValue(pub serde_json::Value);
impl RowFieldValue {
/// In the case where this field value was obtained using a
/// [`Field::Relationship`], the returned JSON will be a [`RowSet`].
/// We cannot express [`RowFieldValue`] as an enum, because
/// [`RowFieldValue`] overlaps with values which have object types.
pub fn as_rowset(self) -> Option<RowSet> {
serde_json::from_value(self.0).ok()
}
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Row Set")]
pub struct RowSet {
/// The results of the aggregates returned by the query
pub aggregates: Option<IndexMap<FieldName, serde_json::Value>>,
/// The rows returned by the query, corresponding to the query's fields
pub rows: Option<Vec<IndexMap<FieldName, RowFieldValue>>>,
/// The results of any grouping operation
pub groups: Option<Vec<Group>>,
}
/// The definition of a scalar type, i.e. types that can be used as the types of columns.
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Scalar Type")]
pub struct ScalarType {
/// A description of valid values for this scalar type.
pub representation: TypeRepresentation,
/// A map from aggregate function names to their definitions. Result type names must be defined scalar types declared in ScalarTypesCapabilities.
pub aggregate_functions: BTreeMap<AggregateFunctionName, AggregateFunctionDefinition>,
/// A map from comparison operator names to their definitions. Argument type names must be defined scalar types declared in ScalarTypesCapabilities.
pub comparison_operators: BTreeMap<ComparisonOperatorName, ComparisonOperatorDefinition>,
/// A map from extraction function names to their definitions.
#[serde(default)]
pub extraction_functions: BTreeMap<ExtractionFunctionName, ExtractionFunctionDefinition>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Schema Response")]
pub struct SchemaResponse {
/// A list of scalar types which will be used as the types of collection columns
pub scalar_types: BTreeMap<ScalarTypeName, ScalarType>,
/// A list of object types which can be used as the types of arguments, or return types of procedures.
/// Names should not overlap with scalar type names.
pub object_types: BTreeMap<ObjectTypeName, ObjectType>,
/// Collections which are available for queries
pub collections: Vec<CollectionInfo>,
/// Functions (i.e. collections which return a single column and row)
pub functions: Vec<FunctionInfo>,
/// Procedures which are available for execution as part of mutations
pub procedures: Vec<ProcedureInfo>,
/// Schema data which is relevant to features enabled by capabilities
pub capabilities: Option<CapabilitySchemaInfo>,
}
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Collection Info")]
pub struct CollectionInfo {
/// The name of the collection
///
/// Note: these names are abstract - there is no requirement that this name correspond to
/// the name of an actual collection in the database.
pub name: CollectionName,
/// Description of the collection
pub description: Option<String>,
/// Any arguments that this collection requires
pub arguments: BTreeMap<ArgumentName, ArgumentInfo>,
/// The name of the collection's object type
#[serde(rename = "type")]
pub collection_type: ObjectTypeName,
/// Any uniqueness constraints enforced on this collection
pub uniqueness_constraints: BTreeMap<String, UniquenessConstraint>,
}
/// Types track the valid representations of values as JSON
#[derive(
Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, JsonSchema,
)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Type")]
pub enum Type {
/// A named type
Named {
/// The name can refer to a scalar or object type
name: TypeName,
},
/// A nullable type
Nullable {
/// The type of the non-null inhabitants of this type
underlying_type: Box<Type>,
},
/// An array type
Array {
/// The type of the elements of the array
element_type: Box<Type>,
},
/// A predicate type for a given object type
Predicate {
/// The object type name
object_type_name: ObjectTypeName,
},
}
/// Representations of scalar types
#[derive(
Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, JsonSchema,
)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(title = "Type Representation")]
pub enum TypeRepresentation {
/// JSON booleans
Boolean,
/// Any JSON string
String,
/// A 8-bit signed integer with a minimum value of -2^7 and a maximum value of 2^7 - 1
Int8,
/// A 16-bit signed integer with a minimum value of -2^15 and a maximum value of 2^15 - 1
Int16,
/// A 32-bit signed integer with a minimum value of -2^31 and a maximum value of 2^31 - 1
Int32,
/// A 64-bit signed integer with a minimum value of -2^63 and a maximum value of 2^63 - 1
Int64,
/// An IEEE-754 single-precision floating-point number
Float32,
/// An IEEE-754 double-precision floating-point number
Float64,
/// Arbitrary-precision integer string
#[serde(rename = "biginteger")]
BigInteger,
/// Arbitrary-precision decimal string
#[serde(rename = "bigdecimal")]
BigDecimal,
/// UUID string (8-4-4-4-12)
#[serde(rename = "uuid")]
UUID,
/// ISO 8601 date
Date,
/// ISO 8601 timestamp
Timestamp,
/// ISO 8601 timestamp-with-timezone
#[serde(rename = "timestamptz")]
TimestampTZ,
/// GeoJSON, per RFC 7946
Geography,
/// GeoJSON Geometry object, per RFC 7946
Geometry,
/// Base64-encoded bytes
Bytes,
/// Arbitrary JSON
#[serde(rename = "json")]
JSON,
/// One of the specified string values
Enum { one_of: Vec<String> },
}
#[derive(
Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, JsonSchema,
)]
#[schemars(title = "Unary Comparison Operator")]
#[serde(rename_all = "snake_case")]
pub enum UnaryComparisonOperator {
IsNull,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(title = "Uniqueness Constraint")]
pub struct UniquenessConstraint {
/// A list of columns which this constraint requires to be unique
pub unique_columns: Vec<FieldName>,
}