Skip to content

Commit

Permalink
Add DontImplCloneOnSqlType attribute.
Browse files Browse the repository at this point in the history
Because, if schema definitions are separated into other crate, implementing Clone for ExistingType will happen compile error.
cf. #93
  • Loading branch information
yagince committed Dec 19, 2023
1 parent 36c44a2 commit 10f8e42
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 2 deletions.
20 changes: 18 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@ use syn::*;
/// * `#[db_rename = "variant"]` specifies the db name for a specific variant.
#[proc_macro_derive(
DbEnum,
attributes(PgType, DieselType, ExistingTypePath, DbValueStyle, db_rename)
attributes(
PgType,
DieselType,
ExistingTypePath,
DbValueStyle,
db_rename,
DontImplCloneOnSqlType
)
)]
pub fn derive(input: TokenStream) -> TokenStream {
let input: DeriveInput = parse_macro_input!(input as DeriveInput);
Expand Down Expand Up @@ -70,6 +77,9 @@ pub fn derive(input: TokenStream) -> TokenStream {
.expect("ExistingTypePath is not a valid token")
});
let new_diesel_mapping = Ident::new(new_diesel_mapping.as_ref(), Span::call_site());

let with_clone = !contains_in_attrs(&input.attrs, "DontImplCloneOnSqlType");

if let Data::Enum(syn::DataEnum {
variants: data_variants,
..
Expand All @@ -81,6 +91,7 @@ pub fn derive(input: TokenStream) -> TokenStream {
&pg_internal_type,
case_style,
&input.ident,
with_clone,
&data_variants,
)
} else {
Expand Down Expand Up @@ -115,6 +126,10 @@ fn val_from_attrs(attrs: &[Attribute], attrname: &str) -> Option<String> {
None
}

fn contains_in_attrs(attrs: &[Attribute], attrname: &str) -> bool {
attrs.iter().any(|e| e.path().is_ident(attrname))
}

/// Defines the casing for the database representation. Follows serde naming convention.
#[derive(Copy, Clone, Debug, PartialEq)]
enum CaseStyle {
Expand Down Expand Up @@ -148,6 +163,7 @@ fn generate_derive_enum_impls(
pg_internal_type: &str,
case_style: CaseStyle,
enum_ty: &Ident,
with_clone: bool,
variants: &syn::punctuated::Punctuated<Variant, syn::token::Comma>,
) -> TokenStream {
let modname = Ident::new(&format!("db_enum_impl_{}", enum_ty), Span::call_site());
Expand Down Expand Up @@ -201,7 +217,7 @@ fn generate_derive_enum_impls(
match existing_mapping_path {
Some(path) => {
let common_impls_on_existing_diesel_mapping = generate_common_impls(path, enum_ty);
let postgres_impl = generate_postgres_impl(path, enum_ty, true);
let postgres_impl = generate_postgres_impl(path, enum_ty, with_clone);
Some(quote! {
#common_impls_on_existing_diesel_mapping
#postgres_impl
Expand Down
2 changes: 2 additions & 0 deletions tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ mod nullable;
#[cfg(feature = "postgres")]
mod pg_array;
#[cfg(feature = "postgres")]
mod pg_clone_impl;
#[cfg(feature = "postgres")]
mod pg_remote_type;
mod simple;
mod value_style;
35 changes: 35 additions & 0 deletions tests/src/pg_clone_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use diesel::prelude::*;

#[cfg(feature = "postgres")]
#[derive(diesel::sql_types::SqlType)]
#[diesel(postgres_type(name = "my_remote_enum"))]
pub struct MyRemoteEnumMapping;

table! {
use diesel::sql_types::Integer;
use super::MyRemoteEnumMapping;
test_remote {
id -> Integer,
my_enum -> MyRemoteEnumMapping,
}
}

#[derive(Insertable, Queryable, Identifiable, Debug, Clone, PartialEq)]
#[diesel(table_name = test_remote)]
struct Data {
id: i32,
my_enum: MyRemoteEnum,
}

#[derive(Debug, PartialEq, Clone, diesel_derive_enum::DbEnum)]
#[ExistingTypePath = "MyRemoteEnumMapping"]
pub enum MyRemoteEnum {
This,
That,
}

#[test]
fn clone_impl_on_sql_type() {
let x = MyRemoteEnumMapping {};
let _ = x.clone();
}

0 comments on commit 10f8e42

Please sign in to comment.