Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/query-engine/sql/src/sql/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ pub enum Returning {
pub enum SelectList {
SelectList(Vec<(ColumnAlias, Expression)>),
SelectStar,
SelectStarComposite(Expression),
}

/// A FROM clause
Expand Down
5 changes: 5 additions & 0 deletions crates/query-engine/sql/src/sql/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ impl SelectList {
SelectList::SelectStar => {
sql.append_syntax("*");
}
SelectList::SelectStarComposite(expr) => {
sql.append_syntax("(");
expr.to_sql(sql);
sql.append_syntax(").*");
}
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions crates/query-engine/sql/src/sql/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ pub fn make_column_alias(name: String) -> ColumnAlias {

// SELECTs //

/// Build a simple 'SELECT (exp).*'
pub fn select_composite(exp: Expression) -> Select {
Select {
with: empty_with(),
select_list: SelectList::SelectStarComposite(exp),
from: None,
joins: vec![],
where_: Where(empty_where()),
group_by: empty_group_by(),
order_by: empty_order_by(),
limit: empty_limit(),
}
}

/// Build a simple select with a select list and the rest are empty.
pub fn simple_select(select_list: Vec<(ColumnAlias, Expression)>) -> Select {
Select {
Expand Down Expand Up @@ -471,6 +485,8 @@ pub fn select_mutation_rowset(
final_select
}

/// Turn all rows of a query result into a single json array of objects.
///
/// Wrap a query that returns multiple rows in the following format:
///
/// ```sql
Expand Down Expand Up @@ -507,6 +523,26 @@ pub fn select_rows_as_json(
select
}

/// Turn each row of a query result into a json object.
///
/// ```sql
/// SELECT row_to_json(<table_alias>) AS <column_alias>
/// FROM <query> as <table_alias>
/// ```
pub fn select_row_as_json(
row_select: Select,
column_alias: ColumnAlias,
table_alias: TableAlias,
) -> Select {
let expression = Expression::RowToJson(TableReference::AliasedTable(table_alias.clone()));
let mut select = simple_select(vec![(column_alias, expression)]);
select.from = Some(From::Select {
select: Box::new(row_select),
alias: table_alias,
});
select
}

/// Wrap a query that returns multiple rows in the following format:
///
/// ```sql
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ pub fn normalize_select(mut select: Select) -> Select {
// select list
select.select_list = match select.select_list {
SelectList::SelectStar => SelectList::SelectStar,
SelectList::SelectStarComposite(exp) => {
SelectList::SelectStarComposite(normalize_expr(exp))
}
SelectList::SelectList(vec) => SelectList::SelectList(
vec.into_iter()
.map(|(alias, expr)| (alias, normalize_expr(expr)))
Expand Down
16 changes: 15 additions & 1 deletion crates/query-engine/translation/src/translation/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Errors for translation.

use query_engine_metadata::metadata::database;
use query_engine_metadata::metadata::{database, Type};

/// A type for translation errors.
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -31,6 +31,10 @@ pub enum Error {
NoProcedureResultFieldsRequested,
UnexpectedStructure(String),
InternalError(String),
NestedFieldNotOfCompositeType {
field_name: String,
actual_type: Type,
},
}

/// Capabilities we don't currently support.
Expand Down Expand Up @@ -132,6 +136,16 @@ impl std::fmt::Display for Error {
Error::NonScalarTypeUsedInOperator { r#type } => {
write!(f, "Non-scalar-type used in operator: {:?}", r#type)
}
Error::NestedFieldNotOfCompositeType {
field_name,
actual_type,
} => {
write!(
f,
"Nested field '{}' not of composite type. Actual type: {:?}",
field_name, actual_type
)
}
}
}
}
55 changes: 55 additions & 0 deletions crates/query-engine/translation/src/translation/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@ pub enum CollectionInfo<'env> {
},
}

#[derive(Debug)]
/// Metadata information about a specific collection.
pub enum CompositeTypeInfo<'env> {
CollectionInfo(CollectionInfo<'env>),
CompositeTypeInfo {
name: String,
info: metadata::CompositeType,
},
}

impl<'request> Env<'request> {
/// Create a new Env by supplying the metadata and relationships.
pub fn new(
Expand All @@ -105,6 +115,29 @@ impl<'request> Env<'request> {
}

/// Lookup a collection's information in the metadata.

pub fn lookup_composite_type(
&self,
type_name: &'request str,
) -> Result<CompositeTypeInfo<'request>, Error> {
let it_is_a_collection = self.lookup_collection(type_name);

match it_is_a_collection {
Ok(collection_info) => Ok(CompositeTypeInfo::CollectionInfo(collection_info)),
Err(Error::CollectionNotFound(_)) => {
let its_a_type = self.metadata.composite_types.0.get(type_name).map(|t| {
CompositeTypeInfo::CompositeTypeInfo {
name: t.name.clone(),
info: t.clone(),
}
});

its_a_type.ok_or(Error::CollectionNotFound(type_name.to_string()))
}
Err(err) => Err(err),
}
}

pub fn lookup_collection(
&self,
collection_name: &'request str,
Expand Down Expand Up @@ -209,6 +242,28 @@ impl CollectionInfo<'_> {
}
}

impl CompositeTypeInfo<'_> {
/// Lookup a column in a collection.
pub fn lookup_column(&self, column_name: &str) -> Result<ColumnInfo, Error> {
match self {
CompositeTypeInfo::CollectionInfo(collection_info) => {
collection_info.lookup_column(column_name)
}
CompositeTypeInfo::CompositeTypeInfo { name, info } => info
.fields
.get(column_name)
.map(|field_info| ColumnInfo {
name: sql::ast::ColumnName(field_info.name.clone()),
r#type: field_info.r#type.clone(),
})
.ok_or(Error::ColumnNotFoundInCollection(
column_name.to_string(),
name.clone(),
)),
}
}
}

impl Default for State {
fn default() -> State {
State {
Expand Down
Loading