Skip to content

Commit

Permalink
It lives!
Browse files Browse the repository at this point in the history
  • Loading branch information
i-am-tom authored and Gil Mizrahi committed Feb 14, 2024
1 parent aac59d3 commit c32cd87
Show file tree
Hide file tree
Showing 17 changed files with 557 additions and 251 deletions.
61 changes: 43 additions & 18 deletions crates/query-engine/sql/src/sql/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,15 +401,22 @@ pub fn select_mutation_rowset(
(output_table_alias, output_column_alias): (TableAlias, ColumnAlias),
(row_table_alias, row_column_alias): (TableAlias, ColumnAlias),
aggregate_table_alias: TableAlias,
row_select: Select,
aggregate_select: Option<Select>,
select: SelectSet,
) -> Select {
let row = vec![(
output_column_alias,
Expression::JsonBuildObject(BTreeMap::from([
("type".to_string(), Box::new(Expression::Value(Value::String("procedure".to_string())))),
("result".to_string(), Box::new(Expression::RowToJson(TableReference::AliasedTable(output_table_alias.clone()))))
]))
(
"type".to_string(),
Box::new(Expression::Value(Value::String("procedure".to_string()))),
),
(
"result".to_string(),
Box::new(Expression::RowToJson(TableReference::AliasedTable(
output_table_alias.clone(),
))),
),
])),
)];

let mut final_select = simple_select(row);
Expand All @@ -418,25 +425,43 @@ pub fn select_mutation_rowset(
select_rows_as_json_for_mutation(row_sel, row_column_alias, row_table_alias.clone())
};

let mut select_star = star_select(From::Select {
alias: row_table_alias.clone(),
select: Box::new(wrap_row(row_select)),
});
match select {
SelectSet::Rows(row_select) => {
let select_star = star_select(From::Select {
alias: row_table_alias.clone(),
select: Box::new(wrap_row(row_select)),
});

final_select.from = Some(From::Select {
alias: output_table_alias,
select: Box::new(select_star),
});
}

SelectSet::Aggregates(aggregate_select) => {
final_select.from = Some(From::Select {
alias: output_table_alias,
select: Box::new(aggregate_select),
});
}

SelectSet::RowsAndAggregates(row_select, aggregate_select) => {
let mut select_star = star_select(From::Select {
alias: row_table_alias.clone(),
select: Box::new(wrap_row(row_select)),
});

match aggregate_select {
None => {}
Some(aggregate_select) => {
select_star.joins = vec![Join::CrossJoin(CrossJoin {
select: Box::new(aggregate_select),
alias: aggregate_table_alias.clone(),
})];
}
}

final_select.from = Some(From::Select {
alias: output_table_alias,
select: Box::new(select_star),
});
final_select.from = Some(From::Select {
alias: output_table_alias,
select: Box::new(select_star),
});
}
};

final_select
}
Expand Down
7 changes: 7 additions & 0 deletions crates/query-engine/translation/src/translation/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub enum Error {
ColumnIsIdentityAlways(String),
MissingColumnInInsert(String, String),
NotImplementedYet(String),
NoProcedureResultFieldsRequested,
UnexpectedStructure(String),
InternalError(String),
}

Expand Down Expand Up @@ -119,6 +121,11 @@ impl std::fmt::Display for Error {
Error::NotImplementedYet(thing) => {
write!(f, "Queries containing {} are not supported.", thing)
}
Error::NoProcedureResultFieldsRequested => write!(
f,
"Procedure requests must ask for 'affected_rows' or use the 'returning' clause."
),
Error::UnexpectedStructure(structure) => write!(f, "Unexpected {}.", structure),
Error::InternalError(thing) => {
write!(f, "Internal error: {}.", thing)
}
Expand Down
150 changes: 122 additions & 28 deletions crates/query-engine/translation/src/translation/mutation/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,49 @@ fn translate_mutation(
alias: table_alias.clone(),
};

let fields = match fields {
Some(models::NestedField::Object(models::NestedObject{ fields })) => Ok(Some(fields)),
Some(models::NestedField::Array(_)) => Err(Error::NotImplementedYet("nested array fields".to_string())),
None => Ok(None)
let (aggregates, fields) = match fields {
Some(models::NestedField::Object(models::NestedObject { fields })) => {
let affected_rows = fields
.get("affected_rows")
.map(|_| indexmap!("affected_rows".to_string() => models::Aggregate::StarCount{}));

let returning = match fields.get("returning") {
Some(field) => match field {
models::Field::Column { fields, .. } => match fields {
Some(nested_fields) => match nested_fields {
models::NestedField::Object(models::NestedObject { fields }) => {
Some(fields.clone())
}
models::NestedField::Array(_) => {
Err(Error::NotImplementedYet("nested array fields".to_string()))?
}
},
None => None,
},
models::Field::Relationship { .. } => Err(Error::UnexpectedStructure(
"relationship variant in procedure fields".to_string(),
))?,
},
None => None,
};

if affected_rows.is_none() && returning.is_none() {
Err(Error::NoProcedureResultFieldsRequested)?
}

Ok((affected_rows, returning))
}

Some(models::NestedField::Array(_)) => {
Err(Error::NotImplementedYet("nested array fields".to_string()))
}
None => Err(Error::NoProcedureResultFieldsRequested)?,
}?;

// define the query selecting from the native query,
// selecting the affected_rows as aggregate and the fields.
let query = models::Query {
aggregates: Some(indexmap!("affected_rows".to_string() => models::Aggregate::StarCount{})),
aggregates,
fields,
limit: None,
offset: None,
Expand Down Expand Up @@ -113,13 +146,21 @@ fn translate_mutation(
};

// fields
let (_, returning_select) = crate::translation::query::root::translate_rows_query(
env,
&mut state,
&current_table,
&from_clause,
&query,
)?;
let returning_select = match &query.fields {
Some(_) => {
let (_, returning_select) = crate::translation::query::root::translate_rows_query(
env,
&mut state,
&current_table,
&from_clause,
&query,
)?;

Some(returning_select)
}

None => None,
};

// affected rows
let aggregate_select = crate::translation::query::root::translate_aggregate_query(
Expand All @@ -141,8 +182,14 @@ fn translate_mutation(
sql::helpers::make_column_alias("returning".to_string()),
),
state.make_table_alias("aggregates".to_string()),
returning_select,
aggregate_select,
match (returning_select, aggregate_select) {
(Some(returning_select), None) => sql::helpers::SelectSet::Rows(returning_select),
(None, Some(aggregate_select)) => sql::helpers::SelectSet::Aggregates(aggregate_select),
(Some(returning_select), Some(aggregate_select)) => {
sql::helpers::SelectSet::RowsAndAggregates(returning_select, aggregate_select)
}
(None, None) => Err(Error::NoProcedureResultFieldsRequested)?,
},
);

let common_table_expression = sql::ast::CommonTableExpression {
Expand Down Expand Up @@ -200,16 +247,49 @@ fn translate_native_query(
alias: table_alias.clone(),
};

let fields = match fields {
Some(models::NestedField::Object(models::NestedObject{ fields })) => Ok(Some(fields)),
Some(models::NestedField::Array(_)) => Err(Error::NotImplementedYet("nested array fields".to_string())),
None => Ok(None)
let (aggregates, fields) = match fields {
Some(models::NestedField::Object(models::NestedObject { fields })) => {
let affected_rows = fields
.get("affected_rows")
.map(|_| indexmap!("affected_rows".to_string() => models::Aggregate::StarCount{}));

let returning = match fields.get("returning") {
Some(field) => match field {
models::Field::Column { fields, .. } => match fields {
Some(nested_fields) => match nested_fields {
models::NestedField::Object(models::NestedObject { fields }) => {
Some(fields.clone())
}
models::NestedField::Array(_) => {
Err(Error::NotImplementedYet("nested array fields".to_string()))?
}
},
None => None,
},
models::Field::Relationship { .. } => Err(Error::UnexpectedStructure(
"relationship variant in procedure fields".to_string(),
))?,
},
None => None,
};

if affected_rows.is_none() && returning.is_none() {
Err(Error::NoProcedureResultFieldsRequested)?
}

Ok((affected_rows, returning))
}

Some(models::NestedField::Array(_)) => {
Err(Error::NotImplementedYet("nested array fields".to_string()))
}
None => Err(Error::NoProcedureResultFieldsRequested)?,
}?;

// define the query selecting from the native query,
// selecting the affected_rows as aggregate and the fields.
let query = models::Query {
aggregates: Some(indexmap!("affected_rows".to_string() => models::Aggregate::StarCount{})),
aggregates,
fields,
limit: None,
offset: None,
Expand All @@ -223,13 +303,21 @@ fn translate_native_query(
};

// fields
let (_, returning_select) = crate::translation::query::root::translate_rows_query(
env,
&mut state,
&current_table,
&from_clause,
&query,
)?;
let returning_select = match &query.fields {
Some(_) => {
let (_, returning_select) = crate::translation::query::root::translate_rows_query(
env,
&mut state,
&current_table,
&from_clause,
&query,
)?;

Some(returning_select)
}

None => None,
};

// affected rows
let aggregate_select = crate::translation::query::root::translate_aggregate_query(
Expand All @@ -251,8 +339,14 @@ fn translate_native_query(
sql::helpers::make_column_alias("returning".to_string()),
),
state.make_table_alias("aggregates".to_string()),
returning_select,
aggregate_select,
match (returning_select, aggregate_select) {
(Some(returning_select), None) => sql::helpers::SelectSet::Rows(returning_select),
(None, Some(aggregate_select)) => sql::helpers::SelectSet::Aggregates(aggregate_select),
(Some(returning_select), Some(aggregate_select)) => {
sql::helpers::SelectSet::RowsAndAggregates(returning_select, aggregate_select)
}
(None, None) => Err(Error::NoProcedureResultFieldsRequested)?,
},
);

// add the procedure native query definition is a with clause.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,26 @@
"track_id": 90
},
"fields": {
"playlist_id": {
"type": "column",
"column": "PlaylistId"
"type": "object",
"fields": {
"affected_rows": {
"column": "affected_rows",
"type": "column"
},

"returning": {
"type": "column",
"column": "returning",
"fields": {
"type": "object",
"fields": {
"playlist_id": {
"type": "column",
"column": "PlaylistId"
}
}
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,30 @@
}
},
"fields": {
"artist_id": {
"type": "column",
"column": "id"
},
"name": {
"type": "column",
"column": "name"
"type": "object",
"fields": {
"affected_rows": {
"column": "affected_rows",
"type": "column"
},

"returning": {
"type": "column",
"column": "returning",
"fields": {
"type": "object",
"fields": {
"artist_id": {
"type": "column",
"column": "id"
},
"name": {
"type": "column",
"column": "name"
}
}
}
}
}
}
}
Expand Down
Loading

0 comments on commit c32cd87

Please sign in to comment.