Skip to content

Commit

Permalink
Merge pull request diesel-rs#3708 from weiznich/table_fixes
Browse files Browse the repository at this point in the history
Emit a better error message if a user writes a `table!` macro without
  • Loading branch information
weiznich committed Aug 15, 2023
1 parent 6eede35 commit e353ece
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
10 changes: 10 additions & 0 deletions diesel_compile_tests/tests/fail/table_without_primary_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#[macro_use] extern crate diesel;

table! {
user {
user_id -> Integer,
name -> Text,
}
}

fn main() {}
14 changes: 14 additions & 0 deletions diesel_compile_tests/tests/fail/table_without_primary_key.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: Neither an explict primary key found nor does an `id` column exist.
Consider explicitly defining a primary key.
For example for specifying `user_id` as primary key:

table! {
user (user_id) {
user_id -> Integer,
name -> Text,
}
}
--> tests/fail/table_without_primary_key.rs:4:5
|
4 | user {
| ^^^^
33 changes: 32 additions & 1 deletion diesel_derives/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,43 @@ pub(crate) fn expand(input: TableDecl) -> TokenStream {
.collect::<Vec<_>>();
let column_names = &column_names;
let primary_key: TokenStream = match input.primary_keys.as_ref() {
None => {
None if column_names.contains(&&syn::Ident::new(
DEFAULT_PRIMARY_KEY_NAME,
proc_macro2::Span::call_site(),
)) =>
{
let id = syn::Ident::new(DEFAULT_PRIMARY_KEY_NAME, proc_macro2::Span::call_site());
parse_quote! {
#id
}
}
None => {
let mut message = format!(
"Neither an explict primary key found nor does an `id` column exist.\n\
Consider explicitly defining a primary key. \n\
For example for specifying `{}` as primary key:\n\n\
table! {{\n",
column_names[0],
);
message += &format!("\t{table_name} ({}) {{\n", &column_names[0]);
for c in &input.column_defs {
let tpe = c
.tpe
.path
.segments
.iter()
.map(|p| p.ident.to_string())
.collect::<Vec<_>>()
.join("::");
message += &format!("\t\t{} -> {tpe},\n", c.column_name);
}
message += "\t}\n}";

let span = input.table_name.span();
return quote::quote_spanned! {span=>
compile_error!(#message);
};
}
Some(a) if a.keys.len() == 1 => {
let k = a.keys.first().unwrap();
parse_quote! {
Expand Down

0 comments on commit e353ece

Please sign in to comment.