Replace i32 with u32 for database columns

Antonio Scandurra created

We never expect to return signed integers and so we shouldn't use
a signed type. I think this was a limitation of sqlx.

Change summary

crates/collab/src/api.rs                     | 10 ++--
crates/collab/src/db.rs                      | 46 ++++++++++-----------
crates/collab/src/db/project.rs              |  2 
crates/collab/src/db/project_collaborator.rs |  2 
crates/collab/src/db/room_participant.rs     |  6 +-
crates/collab/src/db/tests.rs                |  2 
crates/collab/src/db/user.rs                 |  4 
crates/collab/src/db/worktree.rs             |  7 +-
crates/collab/src/integration_tests.rs       |  2 
crates/collab/src/rpc.rs                     |  5 -
10 files changed, 41 insertions(+), 45 deletions(-)

Detailed changes

crates/collab/src/api.rs 🔗

@@ -76,7 +76,7 @@ pub async fn validate_api_token<B>(req: Request<B>, next: Next<B>) -> impl IntoR
 
 #[derive(Debug, Deserialize)]
 struct AuthenticatedUserParams {
-    github_user_id: Option<i32>,
+    github_user_id: Option<u32>,
     github_login: String,
 }
 
@@ -123,14 +123,14 @@ async fn get_users(
 
 #[derive(Deserialize, Debug)]
 struct CreateUserParams {
-    github_user_id: i32,
+    github_user_id: u32,
     github_login: String,
     email_address: String,
     email_confirmation_code: Option<String>,
     #[serde(default)]
     admin: bool,
     #[serde(default)]
-    invite_count: i32,
+    invite_count: u32,
 }
 
 #[derive(Serialize, Debug)]
@@ -208,7 +208,7 @@ struct UpdateUserParams {
 }
 
 async fn update_user(
-    Path(user_id): Path<i32>,
+    Path(user_id): Path<u32>,
     Json(params): Json<UpdateUserParams>,
     Extension(app): Extension<Arc<AppState>>,
     Extension(rpc_server): Extension<Arc<rpc::Server>>,
@@ -230,7 +230,7 @@ async fn update_user(
 }
 
 async fn destroy_user(
-    Path(user_id): Path<i32>,
+    Path(user_id): Path<u32>,
     Extension(app): Extension<Arc<AppState>>,
 ) -> Result<()> {
     app.db.destroy_user(UserId(user_id)).await?;

crates/collab/src/db.rs 🔗

@@ -156,7 +156,7 @@ impl Database {
     pub async fn get_user_by_github_account(
         &self,
         github_login: &str,
-        github_user_id: Option<i32>,
+        github_user_id: Option<u32>,
     ) -> Result<Option<User>> {
         self.transact(|tx| async {
             let tx = tx;
@@ -896,7 +896,7 @@ impl Database {
             user::Entity::update_many()
                 .filter(user::Column::Id.eq(id))
                 .set(user::ActiveModel {
-                    invite_count: ActiveValue::set(count as i32),
+                    invite_count: ActiveValue::set(count),
                     ..Default::default()
                 })
                 .exec(&tx)
@@ -979,9 +979,9 @@ impl Database {
             room_participant::ActiveModel {
                 room_id: ActiveValue::set(room_id),
                 user_id: ActiveValue::set(user_id),
-                answering_connection_id: ActiveValue::set(Some(connection_id.0 as i32)),
+                answering_connection_id: ActiveValue::set(Some(connection_id.0)),
                 calling_user_id: ActiveValue::set(user_id),
-                calling_connection_id: ActiveValue::set(connection_id.0 as i32),
+                calling_connection_id: ActiveValue::set(connection_id.0),
                 ..Default::default()
             }
             .insert(&tx)
@@ -1006,7 +1006,7 @@ impl Database {
                 room_id: ActiveValue::set(room_id),
                 user_id: ActiveValue::set(called_user_id),
                 calling_user_id: ActiveValue::set(calling_user_id),
-                calling_connection_id: ActiveValue::set(calling_connection_id.0 as i32),
+                calling_connection_id: ActiveValue::set(calling_connection_id.0),
                 initial_project_id: ActiveValue::set(initial_project_id),
                 ..Default::default()
             }
@@ -1123,7 +1123,7 @@ impl Database {
                         .and(room_participant::Column::AnsweringConnectionId.is_null()),
                 )
                 .set(room_participant::ActiveModel {
-                    answering_connection_id: ActiveValue::set(Some(connection_id.0 as i32)),
+                    answering_connection_id: ActiveValue::set(Some(connection_id.0)),
                     ..Default::default()
                 })
                 .exec(&tx)
@@ -1485,14 +1485,14 @@ impl Database {
             let project = project::ActiveModel {
                 room_id: ActiveValue::set(participant.room_id),
                 host_user_id: ActiveValue::set(participant.user_id),
-                host_connection_id: ActiveValue::set(connection_id.0 as i32),
+                host_connection_id: ActiveValue::set(connection_id.0),
                 ..Default::default()
             }
             .insert(&tx)
             .await?;
 
             worktree::Entity::insert_many(worktrees.iter().map(|worktree| worktree::ActiveModel {
-                id: ActiveValue::set(worktree.id as i32),
+                id: ActiveValue::set(WorktreeId(worktree.id as u32)),
                 project_id: ActiveValue::set(project.id),
                 abs_path: ActiveValue::set(worktree.abs_path.clone()),
                 root_name: ActiveValue::set(worktree.root_name.clone()),
@@ -1505,7 +1505,7 @@ impl Database {
 
             project_collaborator::ActiveModel {
                 project_id: ActiveValue::set(project.id),
-                connection_id: ActiveValue::set(connection_id.0 as i32),
+                connection_id: ActiveValue::set(connection_id.0),
                 user_id: ActiveValue::set(participant.user_id),
                 replica_id: ActiveValue::set(ReplicaId(0)),
                 is_host: ActiveValue::set(true),
@@ -1533,7 +1533,7 @@ impl Database {
                 .one(&tx)
                 .await?
                 .ok_or_else(|| anyhow!("project not found"))?;
-            if project.host_connection_id == connection_id.0 as i32 {
+            if project.host_connection_id == connection_id.0 {
                 let room_id = project.room_id;
                 project::Entity::delete(project.into_active_model())
                     .exec(&tx)
@@ -1562,7 +1562,7 @@ impl Database {
                 .ok_or_else(|| anyhow!("no such project"))?;
 
             worktree::Entity::insert_many(worktrees.iter().map(|worktree| worktree::ActiveModel {
-                id: ActiveValue::set(worktree.id as i32),
+                id: ActiveValue::set(WorktreeId(worktree.id as u32)),
                 project_id: ActiveValue::set(project.id),
                 abs_path: ActiveValue::set(worktree.abs_path.clone()),
                 root_name: ActiveValue::set(worktree.root_name.clone()),
@@ -1578,7 +1578,7 @@ impl Database {
                         worktree::Column::Id.is_not_in(
                             worktrees
                                 .iter()
-                                .map(|worktree| WorktreeId(worktree.id as i32)),
+                                .map(|worktree| WorktreeId(worktree.id as u32)),
                         ),
                     ),
                 )
@@ -2093,7 +2093,7 @@ impl Database {
 
             if collaborators
                 .iter()
-                .any(|collaborator| collaborator.connection_id == connection_id.0 as i32)
+                .any(|collaborator| collaborator.connection_id == connection_id.0)
             {
                 Ok(collaborators)
             } else {
@@ -2307,8 +2307,8 @@ impl<T> DerefMut for RoomGuard<T> {
 #[derive(Debug, Serialize, Deserialize)]
 pub struct NewUserParams {
     pub github_login: String,
-    pub github_user_id: i32,
-    pub invite_count: i32,
+    pub github_user_id: u32,
+    pub invite_count: u32,
 }
 
 #[derive(Debug)]
@@ -2339,21 +2339,19 @@ macro_rules! id_type {
             PartialOrd,
             Ord,
             Hash,
-            sqlx::Type,
             Serialize,
             Deserialize,
         )]
-        #[sqlx(transparent)]
         #[serde(transparent)]
-        pub struct $name(pub i32);
+        pub struct $name(pub u32);
 
         impl $name {
             #[allow(unused)]
-            pub const MAX: Self = Self(i32::MAX);
+            pub const MAX: Self = Self(u32::MAX);
 
             #[allow(unused)]
             pub fn from_proto(value: u64) -> Self {
-                Self(value as i32)
+                Self(value as u32)
             }
 
             #[allow(unused)]
@@ -2370,7 +2368,7 @@ macro_rules! id_type {
 
         impl From<$name> for sea_query::Value {
             fn from(value: $name) -> Self {
-                sea_query::Value::Int(Some(value.0))
+                sea_query::Value::Unsigned(Some(value.0))
             }
         }
 
@@ -2380,7 +2378,7 @@ macro_rules! id_type {
                 pre: &str,
                 col: &str,
             ) -> Result<Self, sea_orm::TryGetError> {
-                Ok(Self(i32::try_get(res, pre, col)?))
+                Ok(Self(u32::try_get(res, pre, col)?))
             }
         }
 
@@ -2420,11 +2418,11 @@ macro_rules! id_type {
             }
 
             fn array_type() -> sea_query::ArrayType {
-                sea_query::ArrayType::Int
+                sea_query::ArrayType::Unsigned
             }
 
             fn column_type() -> sea_query::ColumnType {
-                sea_query::ColumnType::Integer(None)
+                sea_query::ColumnType::Unsigned(None)
             }
         }
 

crates/collab/src/db/project.rs 🔗

@@ -8,7 +8,7 @@ pub struct Model {
     pub id: ProjectId,
     pub room_id: RoomId,
     pub host_user_id: UserId,
-    pub host_connection_id: i32,
+    pub host_connection_id: u32,
 }
 
 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]

crates/collab/src/db/project_collaborator.rs 🔗

@@ -7,7 +7,7 @@ pub struct Model {
     #[sea_orm(primary_key)]
     pub id: ProjectCollaboratorId,
     pub project_id: ProjectId,
-    pub connection_id: i32,
+    pub connection_id: u32,
     pub user_id: UserId,
     pub replica_id: ReplicaId,
     pub is_host: bool,

crates/collab/src/db/room_participant.rs 🔗

@@ -8,12 +8,12 @@ pub struct Model {
     pub id: RoomParticipantId,
     pub room_id: RoomId,
     pub user_id: UserId,
-    pub answering_connection_id: Option<i32>,
-    pub location_kind: Option<i32>,
+    pub answering_connection_id: Option<u32>,
+    pub location_kind: Option<u32>,
     pub location_project_id: Option<ProjectId>,
     pub initial_project_id: Option<ProjectId>,
     pub calling_user_id: UserId,
-    pub calling_connection_id: i32,
+    pub calling_connection_id: u32,
 }
 
 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]

crates/collab/src/db/tests.rs 🔗

@@ -430,7 +430,7 @@ async fn test_fuzzy_search_users() {
             false,
             NewUserParams {
                 github_login: github_login.into(),
-                github_user_id: i as i32,
+                github_user_id: i as u32,
                 invite_count: 0,
             },
         )

crates/collab/src/db/user.rs 🔗

@@ -8,11 +8,11 @@ pub struct Model {
     #[sea_orm(primary_key)]
     pub id: UserId,
     pub github_login: String,
-    pub github_user_id: Option<i32>,
+    pub github_user_id: Option<u32>,
     pub email_address: Option<String>,
     pub admin: bool,
     pub invite_code: Option<String>,
-    pub invite_count: i32,
+    pub invite_count: u32,
     pub inviter_id: Option<UserId>,
     pub connected_once: bool,
     pub metrics_id: Uuid,

crates/collab/src/db/worktree.rs 🔗

@@ -1,18 +1,17 @@
+use super::{ProjectId, WorktreeId};
 use sea_orm::entity::prelude::*;
 
-use super::ProjectId;
-
 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
 #[sea_orm(table_name = "worktrees")]
 pub struct Model {
     #[sea_orm(primary_key)]
-    pub id: i32,
+    pub id: WorktreeId,
     #[sea_orm(primary_key)]
     pub project_id: ProjectId,
     pub abs_path: String,
     pub root_name: String,
     pub visible: bool,
-    pub scan_id: i64,
+    pub scan_id: u32,
     pub is_complete: bool,
 }
 

crates/collab/src/integration_tests.rs 🔗

@@ -5383,7 +5383,7 @@ async fn test_random_collaboration(
                 false,
                 NewUserParams {
                     github_login: username.clone(),
-                    github_user_id: (ix + 1) as i32,
+                    github_user_id: (ix + 1) as u32,
                     invite_count: 0,
                 },
             )

crates/collab/src/rpc.rs 🔗

@@ -1008,7 +1008,7 @@ async fn join_project(
     let collaborators = project
         .collaborators
         .iter()
-        .filter(|collaborator| collaborator.connection_id != session.connection_id.0 as i32)
+        .filter(|collaborator| collaborator.connection_id != session.connection_id.0)
         .map(|collaborator| proto::Collaborator {
             peer_id: collaborator.connection_id as u32,
             replica_id: collaborator.replica_id.0 as u32,
@@ -1313,8 +1313,7 @@ async fn save_buffer(
         .await
         .project_collaborators(project_id, session.connection_id)
         .await?;
-    collaborators
-        .retain(|collaborator| collaborator.connection_id != session.connection_id.0 as i32);
+    collaborators.retain(|collaborator| collaborator.connection_id != session.connection_id.0);
     let project_connection_ids = collaborators
         .into_iter()
         .map(|collaborator| ConnectionId(collaborator.connection_id as u32));