Skip to content

Commit

Permalink
Merge pull request #72 from nodecosmos/column-type-override
Browse files Browse the repository at this point in the history
Column type override
  • Loading branch information
GoranBrkuljan authored Jan 29, 2025
2 parents c7a9f4d + f0811f9 commit 06b8624
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 53 deletions.
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

0 comments on commit 06b8624

Please sign in to comment.