Skip to content

Commit

Permalink
feat(torii-grpc): start rework to use 1 single query (#2817)
Browse files Browse the repository at this point in the history
* feat(torii-grpc): start rework to use 1 single query

* hashed keys

* start using build sql query singular with left joins

* optimize all queries

* fix: count

* f

* fix count to use having

* f

* print query

* fix keys clause

* having clause keys

* having to hashed keys

* having clause for composite

* fmt

* fmt

* fix: count

* value

* indices

* tests: fix tests

* fix: fmt

* tests: fix by passing the list of expected models

---------

Co-authored-by: glihm <[email protected]>
  • Loading branch information
Larkooo and glihm authored Dec 21, 2024
1 parent 12c96ae commit 3c32891
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 479 deletions.
36 changes: 30 additions & 6 deletions crates/torii/core/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,10 @@ impl ModelReader<Error> for ModelSQLReader {
pub fn build_sql_query(
schemas: &Vec<Ty>,
table_name: &str,
model_relation_table: &str,
entity_relation_column: &str,
where_clause: Option<&str>,
having_clause: Option<&str>,
order_by: Option<&str>,
limit: Option<u32>,
offset: Option<u32>,
Expand Down Expand Up @@ -172,6 +174,7 @@ pub fn build_sql_query(
// Add base table columns
selections.push(format!("{}.id", table_name));
selections.push(format!("{}.keys", table_name));
selections.push(format!("group_concat({model_relation_table}.model_id) as model_ids"));

// Process each model schema
for model in schemas {
Expand All @@ -185,19 +188,37 @@ pub fn build_sql_query(
collect_columns(&model_table, "", model, &mut selections);
}

joins.push(format!(
"JOIN {model_relation_table} ON {table_name}.id = {model_relation_table}.entity_id"
));

let selections_clause = selections.join(", ");
let joins_clause = joins.join(" ");

let mut query = format!("SELECT {} FROM [{}] {}", selections_clause, table_name, joins_clause);

let mut count_query =
format!("SELECT COUNT(DISTINCT {}.id) FROM [{}] {}", table_name, table_name, joins_clause);
// Include model_ids in the subquery and put WHERE before GROUP BY
let mut count_query = format!(
"SELECT COUNT(*) FROM (SELECT {}.id, group_concat({}.model_id) as model_ids FROM [{}] {}",
table_name, model_relation_table, table_name, joins_clause
);

if let Some(where_clause) = where_clause {
query += &format!(" WHERE {}", where_clause);
count_query += &format!(" WHERE {}", where_clause);
}

query += &format!(" GROUP BY {table_name}.id");
count_query += &format!(" GROUP BY {table_name}.id");

if let Some(having_clause) = having_clause {
query += &format!(" HAVING {}", having_clause);
count_query += &format!(" HAVING {}", having_clause);
}

// Close the subquery
count_query += ") AS filtered_entities";

// Use custom order by if provided, otherwise default to event_id DESC
if let Some(order_clause) = order_by {
query += &format!(" ORDER BY {}", order_clause);
Expand Down Expand Up @@ -490,25 +511,28 @@ mod tests {
let query = build_sql_query(
&vec![position, player_config],
"entities",
"entity_model",
"internal_entity_id",
None,
None,
None,
None,
None,
)
.unwrap();

let expected_query =
"SELECT entities.id, entities.keys, [Test-Position].[player] as \
\"Test-Position.player\", [Test-Position].[vec.x] as \"Test-Position.vec.x\", \
[Test-Position].[vec.y] as \"Test-Position.vec.y\", \
"SELECT entities.id, entities.keys, group_concat(entity_model.model_id) as model_ids, \
[Test-Position].[player] as \"Test-Position.player\", [Test-Position].[vec.x] as \
\"Test-Position.vec.x\", [Test-Position].[vec.y] as \"Test-Position.vec.y\", \
[Test-Position].[test_everything] as \"Test-Position.test_everything\", \
[Test-PlayerConfig].[favorite_item] as \"Test-PlayerConfig.favorite_item\", \
[Test-PlayerConfig].[favorite_item.Some] as \
\"Test-PlayerConfig.favorite_item.Some\", [Test-PlayerConfig].[items] as \
\"Test-PlayerConfig.items\" FROM [entities] LEFT JOIN [Test-Position] ON entities.id \
= [Test-Position].internal_entity_id LEFT JOIN [Test-PlayerConfig] ON entities.id = \
[Test-PlayerConfig].internal_entity_id ORDER BY entities.event_id DESC";
[Test-PlayerConfig].internal_entity_id JOIN entity_model ON entities.id = \
entity_model.entity_id GROUP BY entities.id ORDER BY entities.event_id DESC";
assert_eq!(query.0, expected_query);
}
}
4 changes: 4 additions & 0 deletions crates/torii/core/src/sql/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ impl ModelCache {
}

pub async fn models(&self, selectors: &[Felt]) -> Result<Vec<Model>, Error> {
if selectors.is_empty() {
return Ok(self.model_cache.read().await.values().cloned().collect());
}

let mut schemas = Vec::with_capacity(selectors.len());
for selector in selectors {
schemas.push(self.model(selector).await?);
Expand Down
Loading

0 comments on commit 3c32891

Please sign in to comment.