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

Column type override #72

Merged
merged 6 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 43 additions & 39 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion charybdis-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,10 @@ pub fn charybdis_view_model(args: TokenStream, input: TokenStream) -> TokenStrea

#[proc_macro_attribute]
pub fn charybdis_udt_model(_: TokenStream, input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let mut input = parse_macro_input!(input as DeriveInput);

CharybdisFields::proxy_charybdis_attrs_to_scylla(&mut input);
CharybdisFields::strip_charybdis_attributes(&mut input);

let gen = quote! {
#[derive(charybdis::macros::scylla::SerializeValue)]
Expand Down
5 changes: 3 additions & 2 deletions charybdis-migrate/src/args.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use clap::Parser;
use std::env;
use std::path::PathBuf;

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
Expand Down Expand Up @@ -67,5 +66,7 @@ impl Default for Args {
pub(crate) fn get_current_dir() -> String {
let path = env::current_dir().expect("Failed to find project root: Could not get current directory");

PathBuf::from(path).to_str().unwrap().to_string()
path.to_str()
.expect("Failed to find project root: Could not convert path to string")
.to_string()
}
16 changes: 15 additions & 1 deletion charybdis-parser/src/fields.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::{HashMap, HashSet};
use std::str::FromStr;

use darling::FromAttributes;
use syn::spanned::Spanned;
Expand Down Expand Up @@ -44,6 +45,9 @@ pub enum CqlType {
pub struct FieldAttributes {
#[darling(default)]
pub ignore: Option<bool>,

#[darling(default)]
pub column_type: Option<String>,
}

pub struct Field<'a> {
Expand All @@ -52,6 +56,7 @@ pub struct Field<'a> {
pub ty: Type,
pub ty_path: syn::TypePath,
pub outer_type: CqlType,
pub column_type_override: Option<String>,
pub span: proc_macro2::Span,
pub attrs: &'a Vec<syn::Attribute>,
pub ignore: bool,
Expand Down Expand Up @@ -107,6 +112,14 @@ impl<'a> Field<'a> {
FieldAttributes::from_attributes(&field.attrs)
.map(|char_attrs| {
let ignore = char_attrs.ignore.unwrap_or(false);
let column_type =
char_attrs
.column_type
.as_ref()
.map_or(Field::outer_type(&field.ty, ignore), |tname| {
let error = format!("Unknown column type: {}", tname);
CqlType::from_str(tname.as_str()).expect(&error)
});
let ident = field.ident.clone().unwrap();

Field {
Expand All @@ -117,7 +130,8 @@ impl<'a> Field<'a> {
Type::Path(type_path) => type_path.clone(),
_ => panic!("Only type path is supported!"),
},
outer_type: Field::outer_type(&field.ty, ignore),
outer_type: column_type,
column_type_override: char_attrs.column_type,
span: field.span(),
attrs: &field.attrs,
ignore,
Expand Down
4 changes: 3 additions & 1 deletion charybdis-parser/src/schema/code_schema/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ fn extract_schema_object(item_struct: &ItemStruct, model_macro: &ModelMacro) ->

for field in db_fields {
let field_name = field.ident.to_string();
let field_type = type_with_arguments(&field.ty_path);
let field_type = field
.column_type_override
.unwrap_or_else(|| type_with_arguments(&field.ty_path));
let is_static = schema_object.static_columns.contains(&field_name);

schema_object.push_field(field_name, field_type, is_static);
Expand Down
4 changes: 4 additions & 0 deletions charybdis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ serde = { version = "1.0.200", features = ["derive"] }
colored = "2.1.0"
bigdecimal = { version = "0.4.3", features = ["serde"] }


[features]
migrate = ["charybdis-migrate"]

[dev-dependencies]
tokio = "1.42.0"
strum = { version = "0.26.3", features = ["derive"] }
serde = "1.0"
serde_json = "1.0"

[lints]
workspace = true
26 changes: 26 additions & 0 deletions charybdis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -834,3 +834,29 @@ pub struct User {
So field `organization` will be ignored in all operations and
default value will be used when deserializing from other data sources.
It can be used to hold data that is not persisted in database.

## Custom Fields

Any rust type can be used directly in table or UDT definition.
User must choose a ScyllaDB backing type (such as "TinyInt" or "Text")
and implement `SerializeValue` and `DeserializeValue` traits:


```rust
#[charybdis_model(...)]
pub struct User {
id: Uuid,
#[charybdis(column_type = "Text")]
extra_data: CustomField,
}

impl<'frame, 'metadata> DeserializeValue<'frame, 'metadata> for CustomField {
...
}

impl SerializeValue for CustomField {
...
}
```

See `custom_field.rs` integration test for examples using int and text encoding.
Loading