Search code examples
rustrust-diesel

Getting error undefined type or module when defining struct for diesel models


I can't get diesel to run on Rust. The background of this project is a score counting system using postgres as a server to save the scores and diesel to access postgres. When I define a struct in models.rs (named Score), I get this error:

error[E0433]: failed to resolve: use of undeclared type or module `scores`
 --> src/models.rs:7:16
  |
7 | #[table_name = "scores"]
  |                ^^^^^^^^ use of undeclared type or module `scores`

The contents of schema.rs is:

table! {
    scores (name) {
        name -> Varchar,
        points -> Nullable<Int4>,
        subject -> Nullable<Varchar>,
    }
}

Here is my models.rs:

#[macro_use]
use diesel::*;
use diesel::sql_types::*;
use crate::schema::scores::*;

#[derive(Queryable, Insertable, QueryableByName)]
#[table_name = "scores"]
pub struct Score {
    #[sql_type = "Varchar"]
    name: String,
    #[sql_type = "Integer"]
    points: Option<i32>,
    #[sql_type = "Varchar"]
    subject: Option<String>,
}

I'm trying to add entries to it using add_entry.rs:

use super::models::Score;
use diesel::pg::PgConnection;
use crate::schema::*;

pub fn create_score(conn: PgConnection, name: String, score: i32, subject: String) -> () {
    let new_score = Score {
        name: name,
        points: Some(score),
        subject: Some(subject),
    };   

    let ins = diesel::insert_into(scores::table)
        .values(new_score)
        .execute(&conn);
}

In main.rs, I have:

#[macro_use] extern crate diesel;
mod add_entry;
mod connect;
mod models;
mod schema;
use diesel::dsl::sql_query;

fn main() {
    let conn = connect::connect();
    let name = String::from("name");
    let subject = String::from("subject");
    add_entry::create_score(conn, name.clone(), 75, subject.clone());
    //random data
    list_score();
}

fn list_score() {
    let connection = connect::connect();
    let result = sql_query("SELECT * FROM scores");
    println!("{:#?}", result);
}

And in connect.rs(to connect with server) I have:

use dotenv::dotenv;
use diesel::pg::PgConnection;
use diesel::prelude::*;
use std::env;

pub fn connect() -> PgConnection {
     dotenv().ok();
     let database_url = env::var("DATABASE_URL")
         .expect("Cannot get DB URL.");
     PgConnection::establish(&database_url)
         .expect(&format!("Error connecting to {}", database_url));
}

The contents of the dependencies section of my Cargo.toml is

dotenv = "0.9.0" 
diesel = { git = "https://github.com/diesel-rs/diesel", features = ["postgres"] }

To get this error, I ran diesel setup to set up everything, diesel migration run, diesel migration redo, diesel migration run again, and finally cargo build.

My full code can be found in this repository.

What should I do to remove this error? Thanks.


Solution

  • Short answer: You need to import use crate::schema::scores; instead of use crate::schema::scores::*;.

    Longer explanation:

    Diesel's table! macro generates a quite complex module structure, containing several types. Additionally those types are reexported from different locations, for example the dsl module. The derive needs to know the crate::schema::your_table::table type and all types for each column (so crate::schema::your_table::column_a, …). As it cannot access the whole module and has not knowledge about what types are in scope, diesel needs to infer that type somehow. The simplest way to do this is getting the module name from somewhere. That is done via the #[table_name = "your_table"] attribute, which assumes that a module your_table is in scope that contains the corresponding types for table and columns.

    For more details checkout the following documentation: