Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(torii-sqlite): primitive upgrades towards bigger types #2931

Merged
merged 11 commits into from
Feb 6, 2025
38 changes: 38 additions & 0 deletions crates/dojo/types/src/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,44 @@
}
}
}

pub fn can_upgrade_to(&self, other: &Primitive) -> bool {

Check warning on line 407 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L407

Added line #L407 was not covered by tests
use Primitive::*;
match (self, other) {

Check warning on line 409 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L409

Added line #L409 was not covered by tests
// USize is not allowed to upgrade
(USize(_), _) => false,

Check warning on line 411 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L411

Added line #L411 was not covered by tests

// Boolean (no upgrades)
(Bool(_), Bool(_)) => true,

Check warning on line 414 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L414

Added line #L414 was not covered by tests

// Unsigned integer upgrades
(U8(_), U16(_) | U32(_) | USize(_) | U64(_) | U128(_) | Felt252(_)) => true,
(U16(_), U32(_) | USize(_) | U64(_) | U128(_) | Felt252(_)) => true,
(U32(_), USize(_) | U64(_) | U128(_) | Felt252(_)) => true,
(U64(_), U128(_) | Felt252(_)) => true,
(U128(_), Felt252(_)) => true,

Check warning on line 421 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L417-L421

Added lines #L417 - L421 were not covered by tests

// U256 can only upgrade to itself
(U256(_), U256(_)) => true,

Check warning on line 424 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L424

Added line #L424 was not covered by tests

// Signed integer upgrades
(I8(_), I16(_) | I32(_) | I64(_) | I128(_) | Felt252(_)) => true,
(I16(_), I32(_) | I64(_) | I128(_) | Felt252(_)) => true,
(I32(_), I64(_) | I128(_) | Felt252(_)) => true,
(I64(_), I128(_) | Felt252(_)) => true,
(I128(_), Felt252(_)) => true,

Check warning on line 431 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L427-L431

Added lines #L427 - L431 were not covered by tests

// Felt252 and address types
(Felt252(_), ClassHash(_) | ContractAddress(_)) => true,
(ClassHash(_), Felt252(_) | ContractAddress(_)) => true,
(ContractAddress(_), Felt252(_) | ClassHash(_)) => true,

Check warning on line 436 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L434-L436

Added lines #L434 - L436 were not covered by tests
Larkooo marked this conversation as resolved.
Show resolved Hide resolved

// Same type is considered an upgrade (no-op)
(a, b) if std::mem::discriminant(a) == std::mem::discriminant(b) => true,

Check warning on line 439 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L439

Added line #L439 was not covered by tests

_ => false,

Check warning on line 441 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L441

Added line #L441 was not covered by tests
}
}

Check warning on line 443 in crates/dojo/types/src/primitive.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/types/src/primitive.rs#L443

Added line #L443 was not covered by tests
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion crates/torii/indexer/src/processors/upgrade_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
world.model_reader(&namespace, &name).await?
};
let new_schema = model.schema().await?;
let schema_diff = new_schema.diff(&prev_schema);
let schema_diff = prev_schema.diff(&new_schema);

Check warning on line 97 in crates/torii/indexer/src/processors/upgrade_event.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/indexer/src/processors/upgrade_event.rs#L97

Added line #L97 was not covered by tests
// No changes to the schema. This can happen if torii is re-run with a fresh database.
// As the register model fetches the latest schema from the chain.
if schema_diff.is_none() {
Expand Down
2 changes: 1 addition & 1 deletion crates/torii/indexer/src/processors/upgrade_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
world.model_reader(&namespace, &name).await?
};
let new_schema = model.schema().await?;
let schema_diff = new_schema.diff(&prev_schema);
let schema_diff = prev_schema.diff(&new_schema);

Check warning on line 95 in crates/torii/indexer/src/processors/upgrade_model.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/indexer/src/processors/upgrade_model.rs#L95

Added line #L95 was not covered by tests
// No changes to the schema. This can happen if torii is re-run with a fresh database.
// As the register model fetches the latest schema from the chain.
if schema_diff.is_none() {
Expand Down
39 changes: 37 additions & 2 deletions crates/torii/sqlite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use anyhow::{anyhow, Context, Result};
use dojo_types::naming::get_tag;
use dojo_types::primitive::SqlType;
use dojo_types::schema::{Struct, Ty};
use dojo_world::config::WorldMetadata;
use dojo_world::contracts::abigen::model::Layout;
Expand Down Expand Up @@ -887,7 +888,10 @@
alter_table_queries.push(format!("ALTER TABLE [{table_id}] DROP COLUMN [{name}]"));
alter_table_queries
.push(format!("ALTER TABLE [{table_id}] ADD COLUMN [{name}] {sql_type}"));
alter_table_queries.push(format!("UPDATE [{table_id}] SET [{name}] = {sql_value}"));
alter_table_queries.push(format!(
"UPDATE [{table_id}] SET [{name}] = (SELECT {sql_value} FROM tmp_values_{name} \
WHERE tmp_values_{name}.internal_id = [{table_id}].internal_id)"
));

Check warning on line 894 in crates/torii/sqlite/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/sqlite/src/lib.rs#L891-L894

Added lines #L891 - L894 were not covered by tests
alter_table_queries.push(format!("DROP TABLE tmp_values_{name}"));
alter_table_queries.push(format!(
"CREATE INDEX IF NOT EXISTS [idx_{table_id}_{name}] ON [{table_id}] ([{name}]);"
Expand Down Expand Up @@ -1032,7 +1036,38 @@
let column_name =
if column_prefix.is_empty() { "value".to_string() } else { column_prefix };

add_column(&column_name, p.to_sql_type().as_ref());
if let Some(upgrade_diff) = upgrade_diff {
if let Some(old_primitive) = upgrade_diff.as_primitive() {
if old_primitive.can_upgrade_to(p) {

Check warning on line 1041 in crates/torii/sqlite/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/sqlite/src/lib.rs#L1040-L1041

Added lines #L1040 - L1041 were not covered by tests
// For upgrades to larger numeric types, convert to hex string padded to 64
// chars
let sql_value = if old_primitive.to_sql_type() == SqlType::Integer
&& p.to_sql_type() == SqlType::Text

Check warning on line 1045 in crates/torii/sqlite/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/sqlite/src/lib.rs#L1044-L1045

Added lines #L1044 - L1045 were not covered by tests
{
// Convert integer to hex string with '0x' prefix and proper padding
format!("printf('%064x', [{column_name}])")

Check warning on line 1048 in crates/torii/sqlite/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/sqlite/src/lib.rs#L1048

Added line #L1048 was not covered by tests
} else {
format!("[{column_name}]")

Check warning on line 1050 in crates/torii/sqlite/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/sqlite/src/lib.rs#L1050

Added line #L1050 was not covered by tests
};

modify_column(
alter_table_queries,
&column_name,
p.to_sql_type().as_ref(),
&sql_value,
);

Check warning on line 1058 in crates/torii/sqlite/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/sqlite/src/lib.rs#L1053-L1058

Added lines #L1053 - L1058 were not covered by tests
} else {
return Err(anyhow::anyhow!(
"Invalid primitive type upgrade from {:?} to {:?}",
old_primitive,
p
));

Check warning on line 1064 in crates/torii/sqlite/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/sqlite/src/lib.rs#L1060-L1064

Added lines #L1060 - L1064 were not covered by tests
}
}

Check warning on line 1066 in crates/torii/sqlite/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/sqlite/src/lib.rs#L1066

Added line #L1066 was not covered by tests
} else {
// New column
add_column(&column_name, p.to_sql_type().as_ref());
}
}
}

Expand Down
Loading