Use derive macro to create TableRow/PartialTableRow
This commit is contained in:
parent
e27a0d33d7
commit
5fedceb383
@ -9,6 +9,7 @@
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/cove-db/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/bin-test/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/cove-db/cove-db-macros/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
|
||||
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -191,11 +191,21 @@ name = "cove-db"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cove-db-macros",
|
||||
"cove-net-common",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cove-db-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cove-net-client"
|
||||
version = "0.1.0"
|
||||
@ -1863,9 +1873,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.114"
|
||||
version = "2.0.116"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||
checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
14
Cargo.toml
14
Cargo.toml
@ -3,8 +3,10 @@ resolver = "3"
|
||||
members = [
|
||||
"cove-net/common",
|
||||
"cove-net/client",
|
||||
"cove-net/server"
|
||||
, "bin-test", "cove-db"]
|
||||
"cove-net/server",
|
||||
"bin-test",
|
||||
"cove-db",
|
||||
"cove-db/cove-db-macros"]
|
||||
|
||||
[workspace.dependencies]
|
||||
|
||||
@ -13,6 +15,7 @@ async-trait = "0.1.89"
|
||||
anyhow = "1.0.101"
|
||||
hyper = { version = "1", features = ["full"] }
|
||||
http-body-util = { version = "0.1.3", features = ["full"] }
|
||||
rand = "0.10.0"
|
||||
|
||||
cove-net-common = {path = "cove-net/common"}
|
||||
serde_json = "1.0.149"
|
||||
@ -25,4 +28,9 @@ tokio = { version = "1", features = ["full"] }
|
||||
hyper-util = { version = "0.1", features = ["full"] }
|
||||
|
||||
cove-db = {path = "cove-db"}
|
||||
sqlx = { version = "0.8.6", features = [ "runtime-tokio", "tls-rustls-ring", "postgres", "time", "uuid", "json", "derive" ]}
|
||||
sqlx = { version = "0.8.6", features = [ "runtime-tokio", "tls-rustls-ring", "postgres", "time", "uuid", "json", "derive" ]}
|
||||
|
||||
cove-db-macros = {path = "cove-db/cove-db-macros" }
|
||||
syn = {version = "2.0.116", features = ["full"]}
|
||||
quote = {version = "1.0.44"}
|
||||
proc-macro2 = "1.0.106"
|
||||
@ -9,5 +9,5 @@ cove-net-common.workspace = true
|
||||
tokio.workspace = true
|
||||
cove-db.workspace = true
|
||||
sqlx.workspace = true
|
||||
anyhow = "1.0.101"
|
||||
scc = "3.5.6"
|
||||
anyhow.workspace = true
|
||||
scc.workspace = true
|
||||
@ -7,5 +7,6 @@ edition = "2024"
|
||||
sqlx.workspace = true
|
||||
anyhow.workspace = true
|
||||
serde_json.workspace = true
|
||||
cove-db-macros.workspace = true
|
||||
|
||||
cove-net-common.workspace = true
|
||||
12
cove-db/cove-db-macros/Cargo.toml
Normal file
12
cove-db/cove-db-macros/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "cove-db-macros"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn.workspace = true
|
||||
quote.workspace = true
|
||||
proc-macro2.workspace = true
|
||||
257
cove-db/cove-db-macros/src/lib.rs
Normal file
257
cove-db/cove-db-macros/src/lib.rs
Normal file
@ -0,0 +1,257 @@
|
||||
use proc_macro::{TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{parse_str, Data, DeriveInput, Fields};
|
||||
|
||||
#[proc_macro_derive(DeriveTableRow, attributes(table_name))]
|
||||
pub fn derive_table_row(input: TokenStream) -> TokenStream {
|
||||
let ast = syn::parse(input).unwrap();
|
||||
impl_derive_table_row(ast)
|
||||
}
|
||||
|
||||
fn impl_derive_table_row(ast: DeriveInput) -> TokenStream {
|
||||
let table_name: String = {
|
||||
if ast.attrs.len() != 1 {
|
||||
return quote!{compile_error!("The DeriveTableRow macro expects exactly one (1) table_name attribute")}.into();
|
||||
}
|
||||
let attr = ast.attrs.first().unwrap();
|
||||
if attr.path().is_ident("table_name") {
|
||||
if let Ok(args) = attr.parse_args::<syn::LitStr>() {
|
||||
args.value()
|
||||
} else {
|
||||
return quote!{compile_error!("The DeriveTableRow macro's attribute table_name should only consist of a string")}.into();
|
||||
}
|
||||
} else {
|
||||
return quote!{compile_error!("Incorrect attribute name for table_name attribute")}.into();
|
||||
}
|
||||
};
|
||||
|
||||
let name = ast.ident;
|
||||
let partial_name = format_ident!("Partial{}", name);
|
||||
|
||||
let data = ast.data;
|
||||
|
||||
let fields = match data {
|
||||
Data::Struct(data) => {
|
||||
match data.fields {
|
||||
Fields::Named(named_fields) => {
|
||||
named_fields
|
||||
},
|
||||
_ => return quote!{compile_error!("The DeriveTableRow macro can only apply to structs solely consisting of named fields")}.into()
|
||||
}
|
||||
},
|
||||
_ => return quote!{compile_error!("The DeriveTableRow macro can only be applied to structs.")}.into()
|
||||
};
|
||||
|
||||
|
||||
|
||||
let struct_partial_row = {
|
||||
let struct_partial_row_body = {
|
||||
let mut ret = quote!();
|
||||
for field in fields.named.iter() {
|
||||
let name = field.ident.as_ref().unwrap();
|
||||
let ty = &field.ty;
|
||||
ret.extend(quote! {
|
||||
pub #name: Option<#ty>,
|
||||
});
|
||||
}
|
||||
ret
|
||||
};
|
||||
quote! {
|
||||
#[derive(Default)]
|
||||
pub struct #partial_name {
|
||||
#struct_partial_row_body
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
let impl_table_row = quote! {
|
||||
impl crate::rows::TableRow for #name {
|
||||
type Error = anyhow::Error;
|
||||
type PartialRow = #partial_name;
|
||||
|
||||
fn get_table_name() -> &'static str {
|
||||
#table_name
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
let impl_partial_table_row = quote! {
|
||||
impl crate::rows::PartialTableRow for #partial_name {
|
||||
type Error = anyhow::Error;
|
||||
type FullTableRow = #name;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
let impl_insertable_row = {
|
||||
let insert_body = {
|
||||
let mut ret = quote!(
|
||||
crate::part::insert::SqlInsert::with_table(<Self as crate::rows::TableRow>::get_table_name())
|
||||
);
|
||||
|
||||
for field in fields.named.iter() {
|
||||
let name = field.ident.as_ref().unwrap();
|
||||
let quoted_name = format!("{}", name);
|
||||
let ty = &field.ty;
|
||||
ret.extend(
|
||||
quote! {
|
||||
.col::<#ty>(#quoted_name)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
ret
|
||||
};
|
||||
|
||||
let bind_body = {
|
||||
let mut ret = quote! {
|
||||
query
|
||||
};
|
||||
|
||||
let mut idx = 0;
|
||||
let max_idx = fields.named.len();
|
||||
for field in fields.named.iter() {
|
||||
let name = field.ident.as_ref().unwrap();
|
||||
ret.extend(quote! {
|
||||
.bind(&self.#name)
|
||||
});
|
||||
if idx < max_idx-1 {
|
||||
ret.extend(parse_str::<proc_macro2::TokenStream>("?"));
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
ret
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl crate::rows::InsertableRow for #name {
|
||||
fn insert(&'_ self) -> crate::part::insert::SqlInsert {
|
||||
#insert_body
|
||||
}
|
||||
|
||||
fn bind<'a>(&'a self, query: crate::part::BindQuery<'a>) -> Result<crate::part::BindQuery<'a>, Self::Error> {
|
||||
#bind_body
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
let impl_selectable_row = quote! {
|
||||
impl crate::rows::SelectableRow for #partial_name {}
|
||||
};
|
||||
|
||||
let impl_where_row = {
|
||||
let match_body = {
|
||||
let mut ret = quote!();
|
||||
for field in fields.named.iter() {
|
||||
let name = field.ident.as_ref().unwrap();
|
||||
let quoted_name = format!("{}", name);
|
||||
ret.extend(
|
||||
quote! {
|
||||
#quoted_name => query.bind(self.#name.as_ref().unwrap())?,
|
||||
}
|
||||
)
|
||||
}
|
||||
ret
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl crate::rows::WhereRow for #partial_name {
|
||||
fn bind<'a>(&'a self, wheres: crate::part::sql_where::SqlWhere, query: crate::part::BindQuery<'a>) -> Result<crate::part::BindQuery<'a>, Self::Error> {
|
||||
let mut query = query;
|
||||
for (_, col) in wheres.indexed_placeholders {
|
||||
query = match col.as_str() {
|
||||
#match_body
|
||||
_ => return Err(anyhow::anyhow!("No column {col} exists for table users"))
|
||||
}
|
||||
}
|
||||
Ok(query)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
let impl_try_from_pgrow_for_full = {
|
||||
let try_from_body = {
|
||||
let mut ret = quote!();
|
||||
|
||||
for field in fields.named.iter() {
|
||||
let name = field.ident.as_ref().unwrap();
|
||||
let quoted_name = format!("{}", name);
|
||||
ret.extend(
|
||||
quote! {
|
||||
#name: row.try_get(#quoted_name)?,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
ret
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl TryFrom<sqlx::postgres::PgRow> for #name {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(row: sqlx::postgres::PgRow) -> Result<Self, anyhow::Error> {
|
||||
use sqlx::Row;
|
||||
Ok(Self {
|
||||
#try_from_body
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
let impl_from_pgrow_for_partial = {
|
||||
let from_body = {
|
||||
let mut ret = quote!();
|
||||
for field in fields.named.iter() {
|
||||
let name = field.ident.as_ref().unwrap();
|
||||
let quoted_name = format!("{}", name);
|
||||
ret.extend(
|
||||
quote! {
|
||||
#name: row.try_get(#quoted_name).ok(),
|
||||
}
|
||||
)
|
||||
}
|
||||
ret
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl From<sqlx::postgres::PgRow> for #partial_name {
|
||||
fn from(row: sqlx::postgres::PgRow) -> Self {
|
||||
use sqlx::Row;
|
||||
Self {
|
||||
#from_body
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
let mut ret = quote!();
|
||||
ret.extend(struct_partial_row);
|
||||
ret.extend(impl_table_row);
|
||||
ret.extend(impl_partial_table_row);
|
||||
ret.extend(impl_insertable_row);
|
||||
ret.extend(impl_selectable_row);
|
||||
ret.extend(impl_where_row);
|
||||
ret.extend(impl_try_from_pgrow_for_full);
|
||||
ret.extend(impl_from_pgrow_for_partial);
|
||||
|
||||
ret.into()
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
use anyhow::{Error};
|
||||
use sqlx::{Execute, Executor};
|
||||
use sqlx::{Execute};
|
||||
use sqlx::postgres::{ PgQueryResult};
|
||||
use cove_net_common::id::message_type::MessageType;
|
||||
use cove_net_common::id::SnowflakeID;
|
||||
|
||||
@ -1,77 +1,12 @@
|
||||
use anyhow::anyhow;
|
||||
use sqlx::postgres::PgRow;
|
||||
use sqlx::Row;
|
||||
use cove_db_macros::DeriveTableRow;
|
||||
use cove_net_common::id::SnowflakeID;
|
||||
use crate::part::BindQuery;
|
||||
use crate::part::insert::SqlInsert;
|
||||
use crate::part::select::SqlSelect;
|
||||
use crate::part::sql_where::SqlWhere;
|
||||
use crate::rows::{InsertableRow, SelectableRow, TableRow, WhereRow};
|
||||
|
||||
#[derive(DeriveTableRow)]
|
||||
#[table_name("attachments")]
|
||||
pub struct AttachmentRow {
|
||||
pub id: SnowflakeID,
|
||||
pub uploader_id: SnowflakeID,
|
||||
pub channel_id: Option<SnowflakeID>,
|
||||
pub file_size: i32,
|
||||
pub cdn_url: String
|
||||
}
|
||||
|
||||
impl TableRow for AttachmentRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn get_table_name() -> &'static str {
|
||||
"attachments"
|
||||
}
|
||||
}
|
||||
|
||||
impl InsertableRow for AttachmentRow {
|
||||
fn insert(&'_ self) -> SqlInsert {
|
||||
SqlInsert::with_table(Self::get_table_name())
|
||||
.col::<SnowflakeID>("id")
|
||||
.col::<SnowflakeID>("uploader_id")
|
||||
.opt_col::<SnowflakeID>("channel_id")
|
||||
.col::<i32>("file_size")
|
||||
.col::<String>("cdn_url")
|
||||
}
|
||||
|
||||
fn bind<'a>(&'a self, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
query.bind(&self.id)?
|
||||
.bind(&self.uploader_id)?
|
||||
.bind(&self.channel_id)?
|
||||
.bind(&self.file_size)?
|
||||
.bind(&self.cdn_url)
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableRow for AttachmentRow {}
|
||||
|
||||
impl WhereRow for AttachmentRow {
|
||||
fn bind<'a>(&'a self, wheres: SqlWhere, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
let mut query = query;
|
||||
for (_, col) in wheres.indexed_placeholders {
|
||||
query = match col.as_str() {
|
||||
"id" => query.bind(&self.id)?,
|
||||
"uploader_id" => query.bind(&self.uploader_id)?,
|
||||
"channel_id" => query.bind(&self.channel_id)?,
|
||||
"file_size" => query.bind(&self.file_size)?,
|
||||
"cdn_url" => query.bind(&self.cdn_url)?,
|
||||
_ => return Err(anyhow!("No column {col} exists for table attachments"))
|
||||
}
|
||||
}
|
||||
Ok(query)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PgRow> for AttachmentRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: PgRow) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
id: value.try_get("id")?,
|
||||
uploader_id: value.try_get("uploader_id")?,
|
||||
channel_id: value.try_get("channel_id")?,
|
||||
file_size: value.try_get("file_size")?,
|
||||
cdn_url: value.try_get("cdn_url")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,11 @@
|
||||
use anyhow::anyhow;
|
||||
use serde_json::Value;
|
||||
use sqlx::postgres::PgRow;
|
||||
use sqlx::Row;
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use cove_db_macros::DeriveTableRow;
|
||||
use cove_net_common::id::SnowflakeID;
|
||||
use cove_net_common::id::types::channel::ChannelMessageType;
|
||||
use crate::part::BindQuery;
|
||||
use crate::part::insert::SqlInsert;
|
||||
use crate::part::sql_where::SqlWhere;
|
||||
use crate::rows::{InsertableRow, SelectableRow, TableRow, WhereRow};
|
||||
|
||||
#[derive(DeriveTableRow)]
|
||||
#[table_name("channels")]
|
||||
pub struct ChannelRow {
|
||||
pub id: SnowflakeID,
|
||||
pub guild_id: Option<SnowflakeID>,
|
||||
@ -37,120 +33,4 @@ pub struct ChannelRow {
|
||||
|
||||
pub user_limit: i32,
|
||||
pub region: Option<String>
|
||||
}
|
||||
|
||||
impl TableRow for ChannelRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn get_table_name() -> &'static str {
|
||||
"channels"
|
||||
}
|
||||
}
|
||||
|
||||
impl InsertableRow for ChannelRow {
|
||||
fn insert(&'_ self) -> SqlInsert {
|
||||
SqlInsert::with_table(Self::get_table_name())
|
||||
.col::<SnowflakeID>("id")
|
||||
.opt_col::<SnowflakeID>("guild_id")
|
||||
.opt_col::<SnowflakeID>("parent_id")
|
||||
.col::<String>("name")
|
||||
.col::<ChannelMessageType>("channel_type")
|
||||
.col::<i32>("position")
|
||||
.col::<Value>("permission_overwrites")
|
||||
.col::<i32>("rate_limit_per_user")
|
||||
.col::<bool>("nsfw")
|
||||
.col::<bool>("loud")
|
||||
.opt_col::<Value>("thread_metadata")
|
||||
.col::<i32>("member_count")
|
||||
.col::<i32>("message_count")
|
||||
.opt_col::<SnowflakeID>("thread_owner_id")
|
||||
.col::<OffsetDateTime>("created_at")
|
||||
.col::<SnowflakeID>("updated_at")
|
||||
.opt_col::<String>("topic")
|
||||
.col::<i32>("user_limit")
|
||||
.opt_col::<String>("region")
|
||||
}
|
||||
|
||||
fn bind<'a>(&'a self, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
query.bind(&self.id)?
|
||||
.bind(&self.guild_id)?
|
||||
.bind(&self.parent_id)?
|
||||
.bind(&self.name)?
|
||||
.bind(&self.channel_type)?
|
||||
.bind(&self.position)?
|
||||
.bind(&self.permission_overwrites)?
|
||||
.bind(&self.rate_limit_per_user)?
|
||||
.bind(&self.nsfw)?
|
||||
.bind(&self.loud)?
|
||||
.bind(&self.thread_metadata)?
|
||||
.bind(&self.member_count)?
|
||||
.bind(&self.message_count)?
|
||||
.bind(&self.thread_owner_id)?
|
||||
.bind(&self.created_at)?
|
||||
.bind(&self.updated_at)?
|
||||
.bind(&self.topic)?
|
||||
.bind(&self.user_limit)?
|
||||
.bind(&self.region)
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableRow for ChannelRow {}
|
||||
|
||||
impl WhereRow for ChannelRow {
|
||||
fn bind<'a>(&'a self, wheres: SqlWhere, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
let mut query = query;
|
||||
for (_, col) in wheres.indexed_placeholders {
|
||||
query = match col.as_str() {
|
||||
"id" => query.bind(&self.id)?,
|
||||
"guild_id" => query.bind(&self.guild_id)?,
|
||||
"parent_id" => query.bind(&self.parent_id)?,
|
||||
"name" => query.bind(&self.name)?,
|
||||
"channel_type" => query.bind(&self.channel_type)?,
|
||||
"position" => query.bind(&self.position)?,
|
||||
"permission_overwrites" => query.bind(&self.permission_overwrites)?,
|
||||
"rate_limit_per_user" => query.bind(&self.rate_limit_per_user)?,
|
||||
"nsfw" => query.bind(&self.nsfw)?,
|
||||
"loud" => query.bind(&self.loud)?,
|
||||
"thread_metadata" => query.bind(&self.thread_metadata)?,
|
||||
"member_count" => query.bind(&self.member_count)?,
|
||||
"message_count" => query.bind(&self.message_count)?,
|
||||
"thread_owner_id" => query.bind(&self.thread_owner_id)?,
|
||||
"created_at" => query.bind(&self.created_at)?,
|
||||
"updated_at" => query.bind(&self.updated_at)?,
|
||||
"topic" => query.bind(&self.topic)?,
|
||||
"user_limit" => query.bind(&self.user_limit)?,
|
||||
"region" => query.bind(&self.region)?,
|
||||
_ => return Err(anyhow!("No column {col} exists for table attachments"))
|
||||
}
|
||||
}
|
||||
Ok(query)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PgRow> for ChannelRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: PgRow) -> Result<Self, Self::Error> {
|
||||
Ok(Self{
|
||||
id: value.try_get("id")?,
|
||||
guild_id: value.try_get("guild_id")?,
|
||||
parent_id: value.try_get("parent_id")?,
|
||||
name: value.try_get("name")?,
|
||||
channel_type: value.try_get("channel_type")?,
|
||||
position: value.try_get("position")?,
|
||||
permission_overwrites: value.try_get("permission_overwrites")?,
|
||||
rate_limit_per_user: value.try_get("rate_limit_per_user")?,
|
||||
nsfw: value.try_get("nsfw")?,
|
||||
loud: value.try_get("loud")?,
|
||||
thread_metadata: value.try_get("thread_metadata")?,
|
||||
member_count: value.try_get("member_count")?,
|
||||
message_count: value.try_get("message_count")?,
|
||||
thread_owner_id: value.try_get("thread_owner_id")?,
|
||||
created_at: value.try_get("created_at")?,
|
||||
updated_at: value.try_get("updated_at")?,
|
||||
topic: value.try_get("topic")?,
|
||||
user_limit: value.try_get("user_limit")?,
|
||||
region: value.try_get("region")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,13 @@
|
||||
use anyhow::anyhow;
|
||||
use sqlx::postgres::PgRow;
|
||||
use sqlx::Row;
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use cove_db_macros::DeriveTableRow;
|
||||
use cove_net_common::guild::component::default_notification::DefaultMessageNotificationSetting;
|
||||
use cove_net_common::guild::component::explicit_filter::ExplicitContentFilterSetting;
|
||||
use cove_net_common::guild::component::verification_level::VerificationLevelSetting;
|
||||
use cove_net_common::id::SnowflakeID;
|
||||
use crate::part::BindQuery;
|
||||
use crate::part::insert::SqlInsert;
|
||||
use crate::part::sql_where::SqlWhere;
|
||||
use crate::rows::{InsertableRow, SelectableRow, TableRow, WhereRow};
|
||||
|
||||
struct GuildRow {
|
||||
#[derive(DeriveTableRow)]
|
||||
#[table_name("guilds")]
|
||||
pub struct GuildRow {
|
||||
pub id: SnowflakeID,
|
||||
|
||||
pub name: String,
|
||||
@ -49,152 +45,4 @@ struct GuildRow {
|
||||
pub updated_at: OffsetDateTime,
|
||||
pub large: bool,
|
||||
pub member_count: i32
|
||||
}
|
||||
|
||||
impl TableRow for GuildRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn get_table_name() -> &'static str {
|
||||
"guilds"
|
||||
}
|
||||
}
|
||||
|
||||
impl InsertableRow for GuildRow {
|
||||
fn insert(&'_ self) -> SqlInsert {
|
||||
SqlInsert::with_table(Self::get_table_name())
|
||||
.col::<SnowflakeID>("id")
|
||||
.col::<String>("name")
|
||||
.opt_col::<String>("description")
|
||||
.opt_col::<SnowflakeID>("icon")
|
||||
.opt_col::<SnowflakeID>("banner")
|
||||
.opt_col::<SnowflakeID>("splash")
|
||||
.col::<SnowflakeID>("owner_id")
|
||||
.opt_col::<[u8; 8]>("owner_permissions")
|
||||
.col::<String>("region")
|
||||
.col::<i32>("features")
|
||||
.opt_col::<SnowflakeID>("afk_channel_id")
|
||||
.col::<i32>("afk_timeout")
|
||||
.col::<VerificationLevelSetting>("verification_level")
|
||||
.col::<DefaultMessageNotificationSetting>("default_message_notifications")
|
||||
.col::<ExplicitContentFilterSetting>("explicit_content_filter")
|
||||
.opt_col::<SnowflakeID>("system_channel_id")
|
||||
.opt_col::<i32>("system_channel_flags")
|
||||
.arr_col::<SnowflakeID>("premium_boosters")
|
||||
.col::<i32>("premium_tier")
|
||||
.col::<i32>("premium_booster_count")
|
||||
.col::<bool>("widget_enabled")
|
||||
.opt_col::<SnowflakeID>("widget_channel_id")
|
||||
.col::<String>("preferred_locale")
|
||||
.col::<OffsetDateTime>("created_at")
|
||||
.col::<OffsetDateTime>("updated_at")
|
||||
.col::<bool>("large")
|
||||
.col::<i32>("member_count")
|
||||
}
|
||||
|
||||
fn bind<'a>(&'a self, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
query.bind(&self.id)?
|
||||
.bind(&self.name)?
|
||||
.bind(&self.description)?
|
||||
.bind(&self.icon)?
|
||||
.bind(&self.banner)?
|
||||
.bind(&self.splash)?
|
||||
.bind(&self.owner_id)?
|
||||
.bind(&self.owner_permissions)?
|
||||
.bind(&self.region)?
|
||||
.bind(&self.features)?
|
||||
.bind(&self.afk_channel_id)?
|
||||
.bind(&self.afk_timeout)?
|
||||
.bind(&self.verification_level)?
|
||||
.bind(&self.default_message_notifications)?
|
||||
.bind(&self.explicit_content_filter)?
|
||||
.bind(&self.system_channel_id)?
|
||||
.bind(&self.system_channel_flags)?
|
||||
.bind(&self.premium_boosters)?
|
||||
.bind(&self.premium_tier)?
|
||||
.bind(&self.premium_booster_count)?
|
||||
.bind(&self.widget_enabled)?
|
||||
.bind(&self.widget_channel_id)?
|
||||
.bind(&self.preferred_locale)?
|
||||
.bind(&self.created_at)?
|
||||
.bind(&self.updated_at)?
|
||||
.bind(&self.large)?
|
||||
.bind(&self.member_count)
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableRow for GuildRow {}
|
||||
|
||||
impl WhereRow for GuildRow {
|
||||
fn bind<'a>(&'a self, wheres: SqlWhere, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
let mut query = query;
|
||||
for (_, col) in wheres.indexed_placeholders {
|
||||
query = match col.as_str() {
|
||||
"id" => query.bind(&self.id)?,
|
||||
"name" => query.bind(&self.name)?,
|
||||
"description" => query.bind(&self.description)?,
|
||||
"icon" => query.bind(&self.icon)?,
|
||||
"banner" => query.bind(&self.banner)?,
|
||||
"splash" => query.bind(&self.splash)?,
|
||||
"owner_id" => query.bind(&self.owner_id)?,
|
||||
"owner_permissions" => query.bind(&self.owner_permissions)?,
|
||||
"region" => query.bind(&self.region)?,
|
||||
"features" => query.bind(&self.features)?,
|
||||
"afk_channel_id" => query.bind(&self.afk_channel_id)?,
|
||||
"afk_timeout" => query.bind(&self.afk_timeout)?,
|
||||
"verification_level" => query.bind(&self.verification_level)?,
|
||||
"default_message_notifications" => query.bind(&self.default_message_notifications)?,
|
||||
"explicit_content_filter" => query.bind(&self.explicit_content_filter)?,
|
||||
"system_channel_id" => query.bind(&self.system_channel_id)?,
|
||||
"system_channel_flags" => query.bind(&self.system_channel_flags)?,
|
||||
"premium_boosters" => query.bind(&self.premium_boosters)?,
|
||||
"premium_tier" => query.bind(&self.premium_tier)?,
|
||||
"premium_booster_count" => query.bind(&self.premium_booster_count)?,
|
||||
"widget_enabled" => query.bind(&self.widget_enabled)?,
|
||||
"widget_channel_id" => query.bind(&self.widget_channel_id)?,
|
||||
"preferred_locale" => query.bind(&self.preferred_locale)?,
|
||||
"created_at" => query.bind(&self.created_at)?,
|
||||
"updated_at" => query.bind(&self.updated_at)?,
|
||||
"large" => query.bind(&self.large)?,
|
||||
"member_count" => query.bind(&self.member_count)?,
|
||||
_ => return Err(anyhow!("No column {col} exists for table attachments"))
|
||||
}
|
||||
}
|
||||
Ok(query)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PgRow> for GuildRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: PgRow) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
id: value.try_get("id")?,
|
||||
name: value.try_get("name")?,
|
||||
description: value.try_get("description")?,
|
||||
icon: value.try_get("icon")?,
|
||||
banner: value.try_get("banner")?,
|
||||
splash: value.try_get("splash")?,
|
||||
owner_id: value.try_get("owner_id")?,
|
||||
owner_permissions: value.try_get("owner_permissions")?,
|
||||
region: value.try_get("region")?,
|
||||
features: value.try_get("features")?,
|
||||
afk_channel_id: value.try_get("afk_channel_id")?,
|
||||
afk_timeout: value.try_get("afk_timeout")?,
|
||||
verification_level: value.try_get("verification_level")?,
|
||||
default_message_notifications: value.try_get("default_message_notifications")?,
|
||||
explicit_content_filter: value.try_get("explicit_content_filter")?,
|
||||
system_channel_id: value.try_get("system_channel_id")?,
|
||||
system_channel_flags: value.try_get("system_channel_flags")?,
|
||||
premium_boosters: value.try_get("premium_boosters")?,
|
||||
premium_tier: value.try_get("premium_tier")?,
|
||||
premium_booster_count: value.try_get("premium_booster_count")?,
|
||||
widget_enabled: value.try_get("widget_enabled")?,
|
||||
widget_channel_id: value.try_get("widget_channel_id")?,
|
||||
preferred_locale: value.try_get("preferred_locale")?,
|
||||
created_at: value.try_get("created_at")?,
|
||||
updated_at: value.try_get("updated_at")?,
|
||||
large: value.try_get("large")?,
|
||||
member_count: value.try_get("member_count")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,10 @@
|
||||
use anyhow::anyhow;
|
||||
use sqlx::postgres::PgRow;
|
||||
use sqlx::Row;
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use cove_db_macros::DeriveTableRow;
|
||||
use cove_net_common::id::SnowflakeID;
|
||||
use crate::part::BindQuery;
|
||||
use crate::part::insert::SqlInsert;
|
||||
use crate::part::sql_where::SqlWhere;
|
||||
use crate::rows::{InsertableRow, SelectableRow, TableRow, WhereRow};
|
||||
|
||||
struct GuildMemberRow {
|
||||
#[derive(DeriveTableRow)]
|
||||
#[table_name("guild_members")]
|
||||
pub struct GuildMemberRow {
|
||||
pub guild_id: SnowflakeID,
|
||||
pub user_id: SnowflakeID,
|
||||
|
||||
@ -26,92 +22,4 @@ struct GuildMemberRow {
|
||||
pub timed_out_until: Option<OffsetDateTime>,
|
||||
|
||||
pub updated_at: OffsetDateTime,
|
||||
}
|
||||
|
||||
impl TableRow for GuildMemberRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn get_table_name() -> &'static str {
|
||||
"guild_members"
|
||||
}
|
||||
}
|
||||
|
||||
impl InsertableRow for GuildMemberRow {
|
||||
fn insert(&'_ self) -> SqlInsert {
|
||||
SqlInsert::with_table(Self::get_table_name())
|
||||
.col::<SnowflakeID>("guild_id")
|
||||
.col::<SnowflakeID>("user_id")
|
||||
.opt_col::<String>("nick")
|
||||
.col::<OffsetDateTime>("joined_at")
|
||||
.arr_col::<SnowflakeID>("roles")
|
||||
.opt_col::<OffsetDateTime>("boosting_since")
|
||||
.opt_col::<SnowflakeID>("voice_channel_id")
|
||||
.col::<bool>("deafened")
|
||||
.col::<bool>("muted")
|
||||
.col::<bool>("pending")
|
||||
.opt_col::<OffsetDateTime>("timed_out_until")
|
||||
.col::<OffsetDateTime>("updated_at")
|
||||
}
|
||||
|
||||
fn bind<'a>(&'a self, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
query.bind(&self.guild_id)?
|
||||
.bind(&self.user_id)?
|
||||
.bind(&self.nick)?
|
||||
.bind(&self.joined_at)?
|
||||
.bind(&self.roles)?
|
||||
.bind(&self.boosting_since)?
|
||||
.bind(&self.voice_channel_id)?
|
||||
.bind(&self.deafened)?
|
||||
.bind(&self.muted)?
|
||||
.bind(&self.pending)?
|
||||
.bind(&self.timed_out_until)?
|
||||
.bind(&self.updated_at)
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableRow for GuildMemberRow {}
|
||||
|
||||
impl WhereRow for GuildMemberRow {
|
||||
fn bind<'a>(&'a self, wheres: SqlWhere, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
let mut query = query;
|
||||
for (_, col) in wheres.indexed_placeholders {
|
||||
query = match col.as_str() {
|
||||
"guild_id" => query.bind(&self.guild_id)?,
|
||||
"user_id" => query.bind(&self.user_id)?,
|
||||
"nick" => query.bind(&self.nick)?,
|
||||
"joined_at" => query.bind(&self.joined_at)?,
|
||||
"roles" => query.bind(&self.roles)?,
|
||||
"boosting_since" => query.bind(&self.boosting_since)?,
|
||||
"voice_channel_id" => query.bind(&self.voice_channel_id)?,
|
||||
"deafened" => query.bind(&self.deafened)?,
|
||||
"muted" => query.bind(&self.muted)?,
|
||||
"pending" => query.bind(&self.pending)?,
|
||||
"timed_out_until" => query.bind(&self.timed_out_until)?,
|
||||
"updated_at" => query.bind(&self.updated_at)?,
|
||||
_ => return Err(anyhow!("No column {col} exists for table attachments"))
|
||||
}
|
||||
}
|
||||
Ok(query)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PgRow> for GuildMemberRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: PgRow) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
guild_id: value.try_get("guild_id")?,
|
||||
user_id: value.try_get("user_id")?,
|
||||
nick: value.try_get("nick")?,
|
||||
joined_at: value.try_get("joined_at")?,
|
||||
roles: value.try_get("roles")?,
|
||||
boosting_since: value.try_get("boosting_since")?,
|
||||
voice_channel_id: value.try_get("voice_channel_id")?,
|
||||
deafened: value.try_get("deafened")?,
|
||||
muted: value.try_get("muted")?,
|
||||
pending: value.try_get("pending")?,
|
||||
timed_out_until: value.try_get("timed_out_until")?,
|
||||
updated_at: value.try_get("updated_at")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,11 @@
|
||||
use anyhow::anyhow;
|
||||
use sqlx::postgres::PgRow;
|
||||
use sqlx::Row;
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use cove_db_macros::DeriveTableRow;
|
||||
use cove_net_common::id::SnowflakeID;
|
||||
use cove_net_common::id::types::text::TextMessageType;
|
||||
use cove_net_common::message::c2s::text::text::TextEmbed;
|
||||
use crate::part::BindQuery;
|
||||
use crate::part::insert::SqlInsert;
|
||||
use crate::part::sql_where::SqlWhere;
|
||||
use crate::rows::{InsertableRow, SelectableRow, TableRow, WhereRow};
|
||||
|
||||
#[derive(DeriveTableRow)]
|
||||
#[table_name("messages")]
|
||||
pub struct MessageRow {
|
||||
pub id: SnowflakeID,
|
||||
pub channel_id: SnowflakeID,
|
||||
@ -36,120 +32,4 @@ pub struct MessageRow {
|
||||
|
||||
pub created_at: OffsetDateTime,
|
||||
pub updated_at: OffsetDateTime,
|
||||
}
|
||||
|
||||
impl TableRow for MessageRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn get_table_name() -> &'static str {
|
||||
"messages"
|
||||
}
|
||||
}
|
||||
|
||||
impl InsertableRow for MessageRow {
|
||||
fn insert(&'_ self) -> SqlInsert {
|
||||
SqlInsert::with_table(Self::get_table_name())
|
||||
.col::<SnowflakeID>("id")
|
||||
.col::<SnowflakeID>("channel_id")
|
||||
.opt_col::<SnowflakeID>("guild_id")
|
||||
.col::<SnowflakeID>("author_id")
|
||||
.col::<String>("content")
|
||||
.col::<OffsetDateTime>("timestamp")
|
||||
.opt_col::<OffsetDateTime>("edited_timestamp")
|
||||
.col::<bool>("tts")
|
||||
.opt_arr_col::<SnowflakeID>("mentions")
|
||||
.col::<bool>("mention_everyone")
|
||||
.opt_arr_col::<TextEmbed>("embeds")
|
||||
.opt_arr_col::<SnowflakeID>("attachments")
|
||||
.opt_col::<SnowflakeID>("reply_message_id")
|
||||
.opt_col::<SnowflakeID>("application_id")
|
||||
.col::<TextMessageType>("message_type")
|
||||
.opt_col::<String>("thread_name")
|
||||
.opt_col::<i32>("auto_archive_duration")
|
||||
.col::<OffsetDateTime>("created_at")
|
||||
.col::<OffsetDateTime>("updated_at")
|
||||
}
|
||||
|
||||
fn bind<'a>(&'a self, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
query.bind(&self.id)?
|
||||
.bind(&self.channel_id)?
|
||||
.bind(&self.guild_id)?
|
||||
.bind(&self.author_id)?
|
||||
.bind(&self.content)?
|
||||
.bind(&self.timestamp)?
|
||||
.bind(&self.edited_timestamp)?
|
||||
.bind(&self.tts)?
|
||||
.bind(&self.mentions)?
|
||||
.bind(&self.mention_everyone)?
|
||||
.bind(&self.embeds)?
|
||||
.bind(&self.attachments)?
|
||||
.bind(&self.reply_message_id)?
|
||||
.bind(&self.application_id)?
|
||||
.bind(&self.message_type)?
|
||||
.bind(&self.thread_name)?
|
||||
.bind(&self.auto_archive_duration)?
|
||||
.bind(&self.created_at)?
|
||||
.bind(&self.updated_at)
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableRow for MessageRow {}
|
||||
|
||||
impl WhereRow for MessageRow {
|
||||
fn bind<'a>(&'a self, wheres: SqlWhere, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
let mut query = query;
|
||||
for (_, col) in wheres.indexed_placeholders {
|
||||
query = match col.as_str() {
|
||||
"id" => query.bind(&self.id)?,
|
||||
"channel_id" => query.bind(&self.channel_id)?,
|
||||
"guild_id" => query.bind(&self.guild_id)?,
|
||||
"author_id" => query.bind(&self.author_id)?,
|
||||
"content" => query.bind(&self.content)?,
|
||||
"timestamp" => query.bind(&self.timestamp)?,
|
||||
"edited_timestamp" => query.bind(&self.edited_timestamp)?,
|
||||
"tts" => query.bind(&self.tts)?,
|
||||
"mentions" => query.bind(&self.mentions)?,
|
||||
"mention_everyone" => query.bind(&self.mention_everyone)?,
|
||||
"embeds" => query.bind(&self.embeds)?,
|
||||
"attachments" => query.bind(&self.attachments)?,
|
||||
"reply_message_id" => query.bind(&self.reply_message_id)?,
|
||||
"application_id" => query.bind(&self.application_id)?,
|
||||
"message_type" => query.bind(&self.message_type)?,
|
||||
"thread_name" => query.bind(&self.thread_name)?,
|
||||
"auto_archive_duration" => query.bind(&self.auto_archive_duration)?,
|
||||
"created_at" => query.bind(&self.created_at)?,
|
||||
"updated_at" => query.bind(&self.updated_at)?,
|
||||
_ => return Err(anyhow!("No column {col} exists for table attachments"))
|
||||
}
|
||||
}
|
||||
Ok(query)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PgRow> for MessageRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: PgRow) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
id: value.try_get("id")?,
|
||||
channel_id: value.try_get("channel_id")?,
|
||||
guild_id: value.try_get("guild_id")?,
|
||||
author_id: value.try_get("author_id")?,
|
||||
content: value.try_get("content")?,
|
||||
timestamp: value.try_get("timestamp")?,
|
||||
edited_timestamp: value.try_get("edited_timestamp")?,
|
||||
tts: value.try_get("tts")?,
|
||||
mentions: value.try_get("mentions")?,
|
||||
mention_everyone: value.try_get("mention_everyone")?,
|
||||
embeds: value.try_get("embeds")?,
|
||||
attachments: value.try_get("attachments")?,
|
||||
reply_message_id: value.try_get("reply_message_id")?,
|
||||
application_id: value.try_get("application_id")?,
|
||||
message_type: value.try_get("message_type")?,
|
||||
thread_name: value.try_get("thread_name")?,
|
||||
auto_archive_duration: value.try_get("auto_archive_duration")?,
|
||||
created_at: value.try_get("created_at")?,
|
||||
updated_at: value.try_get("updated_at")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,12 @@ use crate::part::insert::SqlInsert;
|
||||
use crate::part::select::SqlSelect;
|
||||
use crate::part::sql_where::SqlWhere;
|
||||
|
||||
pub mod attachment;
|
||||
pub mod channel;
|
||||
pub mod guild;
|
||||
pub mod guild_member;
|
||||
pub mod message;
|
||||
pub mod nonce;
|
||||
pub mod user;
|
||||
|
||||
pub trait TableRow {
|
||||
|
||||
@ -1,77 +1,13 @@
|
||||
use anyhow::anyhow;
|
||||
use sqlx::postgres::PgRow;
|
||||
use sqlx::Row;
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use cove_db_macros::DeriveTableRow;
|
||||
use cove_net_common::id::SnowflakeID;
|
||||
use crate::part::BindQuery;
|
||||
use crate::part::insert::SqlInsert;
|
||||
use crate::part::sql_where::SqlWhere;
|
||||
use crate::rows::{InsertableRow, SelectableRow, TableRow, WhereRow};
|
||||
|
||||
struct NonceRow {
|
||||
#[derive(DeriveTableRow)]
|
||||
#[table_name("pending_nonces")]
|
||||
pub struct NonceRow {
|
||||
pub nonce: String,
|
||||
pub channel_id: SnowflakeID,
|
||||
pub author_id: SnowflakeID,
|
||||
pub created_at: OffsetDateTime,
|
||||
pub expires_at: OffsetDateTime,
|
||||
}
|
||||
|
||||
impl TableRow for NonceRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn get_table_name() -> &'static str {
|
||||
"pending_nonces"
|
||||
}
|
||||
}
|
||||
|
||||
impl InsertableRow for NonceRow {
|
||||
fn insert(&'_ self) -> SqlInsert {
|
||||
SqlInsert::with_table(Self::get_table_name())
|
||||
.col::<String>("nonce")
|
||||
.col::<SnowflakeID>("channel_id")
|
||||
.col::<SnowflakeID>("author_id")
|
||||
.col::<OffsetDateTime>("created_at")
|
||||
.col::<OffsetDateTime>("expires_at")
|
||||
}
|
||||
|
||||
fn bind<'a>(&'a self, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
query.bind(&self.nonce)?
|
||||
.bind(&self.channel_id)?
|
||||
.bind(&self.author_id)?
|
||||
.bind(&self.created_at)?
|
||||
.bind(&self.expires_at)
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableRow for NonceRow {}
|
||||
|
||||
impl WhereRow for NonceRow {
|
||||
fn bind<'a>(&'a self, wheres: SqlWhere, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
let mut query = query;
|
||||
for (_, col) in wheres.indexed_placeholders {
|
||||
query = match col.as_str() {
|
||||
"nonce" => query.bind(&self.nonce)?,
|
||||
"channel_id" => query.bind(&self.channel_id)?,
|
||||
"author_id" => query.bind(&self.author_id)?,
|
||||
"created_at" => query.bind(&self.created_at)?,
|
||||
"expires_at" => query.bind(&self.expires_at)?,
|
||||
_ => return Err(anyhow!("No column {col} exists for table attachments"))
|
||||
}
|
||||
}
|
||||
Ok(query)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PgRow> for NonceRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: PgRow) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
nonce: value.try_get("nonce")?,
|
||||
channel_id: value.try_get("channel_id")?,
|
||||
author_id: value.try_get("author_id")?,
|
||||
created_at: value.try_get("created_at")?,
|
||||
expires_at: value.try_get("expires_at")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,11 @@
|
||||
use anyhow::anyhow;
|
||||
use serde_json::Value;
|
||||
use sqlx::postgres::PgRow;
|
||||
use sqlx::Row;
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use cove_db_macros::DeriveTableRow;
|
||||
use cove_net_common::id::SnowflakeID;
|
||||
use crate::part::BindQuery;
|
||||
use crate::part::insert::SqlInsert;
|
||||
use crate::part::sql_where::SqlWhere;
|
||||
use crate::rows::{InsertableRow, PartialTableRow, SelectableRow, TableRow, WhereRow};
|
||||
use crate::types::user_status::UserStatus;
|
||||
|
||||
#[derive(DeriveTableRow)]
|
||||
#[table_name("users")]
|
||||
pub struct UserRow {
|
||||
pub id: SnowflakeID,
|
||||
pub username: String,
|
||||
@ -30,176 +26,4 @@ pub struct UserRow {
|
||||
pub preferences: Value,
|
||||
pub created_at: OffsetDateTime,
|
||||
pub updated_at: OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PartialUserRow {
|
||||
pub id: Option<SnowflakeID>,
|
||||
pub username: Option<String>,
|
||||
pub discriminator: Option<String>,
|
||||
pub avatar_hash: Option<Option<String>>,
|
||||
pub email: Option<String>,
|
||||
pub email_verified: Option<bool>,
|
||||
pub password_hash: Option<String>,
|
||||
pub mfa_enabled: Option<bool>,
|
||||
pub mfa_secret: Option<Option<String>>,
|
||||
pub status: Option<UserStatus>,
|
||||
pub public_flags: Option<i64>,
|
||||
pub locale: Option<String>,
|
||||
pub premium_since: Option<Option<OffsetDateTime>>,
|
||||
pub premium_end: Option<Option<OffsetDateTime>>,
|
||||
pub bot: Option<bool>,
|
||||
pub bot_oauth_scopes: Option<Value>,
|
||||
pub preferences: Option<Value>,
|
||||
pub created_at: Option<OffsetDateTime>,
|
||||
pub updated_at: Option<OffsetDateTime>,
|
||||
}
|
||||
|
||||
impl TableRow for UserRow {
|
||||
type Error = anyhow::Error;
|
||||
type PartialRow = PartialUserRow;
|
||||
|
||||
fn get_table_name() -> &'static str {
|
||||
"users"
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialTableRow for PartialUserRow {
|
||||
type Error = anyhow::Error;
|
||||
type FullTableRow = UserRow;
|
||||
|
||||
}
|
||||
|
||||
impl InsertableRow for UserRow {
|
||||
fn insert(&'_ self) -> SqlInsert {
|
||||
SqlInsert::with_table(Self::get_table_name())
|
||||
.col::<SnowflakeID>("id")
|
||||
.col::<String>("username")
|
||||
.col::<String>("discriminator")
|
||||
.opt_col::<String>("avatar_hash")
|
||||
.col::<String>("email")
|
||||
.col::<bool>("email_verified")
|
||||
.col::<String>("password_hash")
|
||||
.col::<bool>("mfa_enabled")
|
||||
.opt_col::<String>("mfa_secret")
|
||||
.col::<UserStatus>("status")
|
||||
.col::<i64>("public_flags")
|
||||
.col::<String>("locale")
|
||||
.opt_col::<OffsetDateTime>("premium_since")
|
||||
.opt_col::<OffsetDateTime>("premium_end")
|
||||
.col::<bool>("bot")
|
||||
.col::<Value>("bot_oauth_scopes")
|
||||
.col::<Value>("preferences")
|
||||
.col::<OffsetDateTime>("created_at")
|
||||
.col::<OffsetDateTime>("updated_at")
|
||||
}
|
||||
|
||||
fn bind<'a>(&'a self, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
query.bind(&self.id)?
|
||||
.bind(&self.username)?
|
||||
.bind(&self.discriminator)?
|
||||
.bind(&self.avatar_hash)?
|
||||
.bind(&self.email)?
|
||||
.bind(&self.email_verified)?
|
||||
.bind(&self.password_hash)?
|
||||
.bind(&self.mfa_enabled)?
|
||||
.bind(&self.mfa_secret)?
|
||||
.bind(&self.status)?
|
||||
.bind(&self.public_flags)?
|
||||
.bind(&self.locale)?
|
||||
.bind(&self.premium_since)?
|
||||
.bind(&self.premium_end)?
|
||||
.bind(&self.bot)?
|
||||
.bind(&self.bot_oauth_scopes)?
|
||||
.bind(&self.preferences)?
|
||||
.bind(&self.created_at)?
|
||||
.bind(&self.updated_at)
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableRow for PartialUserRow {}
|
||||
|
||||
impl WhereRow for PartialUserRow {
|
||||
fn bind<'a>(&'a self, wheres: SqlWhere, query: BindQuery<'a>) -> Result<BindQuery<'a>, Self::Error> {
|
||||
let mut query = query;
|
||||
for (_, col) in wheres.indexed_placeholders {
|
||||
query = match col.as_str() {
|
||||
"id" => query.bind(self.id.as_ref().unwrap())?,
|
||||
"username" => query.bind(self.username.as_ref().unwrap())?,
|
||||
"discriminator" => query.bind(self.discriminator.as_ref().unwrap())?,
|
||||
"avatar_hash" => query.bind(self.avatar_hash.as_ref().unwrap())?,
|
||||
"email" => query.bind(self.email.as_ref().unwrap())?,
|
||||
"email_verified" => query.bind(self.email_verified.as_ref().unwrap())?,
|
||||
"password_hash" => query.bind(self.password_hash.as_ref().unwrap())?,
|
||||
"mfa_enabled" => query.bind(self.mfa_enabled.as_ref().unwrap())?,
|
||||
"mfa_secret" => query.bind(self.mfa_secret.as_ref().unwrap())?,
|
||||
"status" => query.bind(self.status.as_ref().unwrap())?,
|
||||
"public_flags" => query.bind(self.public_flags.as_ref().unwrap())?,
|
||||
"locale" => query.bind(self.locale.as_ref().unwrap())?,
|
||||
"premium_since" => query.bind(self.premium_since.as_ref().unwrap())?,
|
||||
"premium_end" => query.bind(self.premium_end.as_ref().unwrap())?,
|
||||
"bot" => query.bind(self.bot.as_ref().unwrap())?,
|
||||
"bot_oauth_scopes" => query.bind(self.bot_oauth_scopes.as_ref().unwrap())?,
|
||||
"preferences" => query.bind(self.preferences.as_ref().unwrap())?,
|
||||
"created_at" => query.bind(self.created_at.as_ref().unwrap())?,
|
||||
"updated_at" => query.bind(self.updated_at.as_ref().unwrap())?,
|
||||
_ => return Err(anyhow!("No column {col} exists for table users"))
|
||||
}
|
||||
}
|
||||
Ok(query)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PgRow> for UserRow {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(row: PgRow) -> Result<Self, anyhow::Error> {
|
||||
Ok(Self {
|
||||
id: row.try_get("id")?,
|
||||
username: row.try_get("username")?,
|
||||
discriminator: row.try_get("discriminator")?,
|
||||
avatar_hash: row.try_get("avatar_hash")?,
|
||||
email: row.try_get("email")?,
|
||||
email_verified: row.try_get("email_verified")?,
|
||||
password_hash: row.try_get("password_hash")?,
|
||||
mfa_enabled: row.try_get("mfa_enabled")?,
|
||||
mfa_secret: row.try_get("mfa_secret")?,
|
||||
status: row.try_get("status")?,
|
||||
public_flags: row.try_get("public_flags")?,
|
||||
locale: row.try_get("locale")?,
|
||||
premium_since: row.try_get("premium_since")?,
|
||||
premium_end: row.try_get("premium_end")?,
|
||||
bot: row.try_get("bot")?,
|
||||
bot_oauth_scopes: row.try_get("bot_oauth_scopes")?,
|
||||
preferences: row.try_get("preferences")?,
|
||||
created_at: row.try_get("created_at")?,
|
||||
updated_at: row.try_get("updated_at")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PgRow> for PartialUserRow {
|
||||
fn from(row: PgRow) -> Self {
|
||||
Self {
|
||||
id: row.try_get("id").ok(),
|
||||
username: row.try_get("username").ok(),
|
||||
discriminator: row.try_get("discriminator").ok(),
|
||||
avatar_hash: row.try_get("avatar_hash").ok(),
|
||||
email: row.try_get("email").ok(),
|
||||
email_verified: row.try_get("email_verified").ok(),
|
||||
password_hash: row.try_get("password_hash").ok(),
|
||||
mfa_enabled: row.try_get("mfa_enabled").ok(),
|
||||
mfa_secret: row.try_get("mfa_secret").ok(),
|
||||
status: row.try_get("status").ok(),
|
||||
public_flags: row.try_get("public_flags").ok(),
|
||||
locale: row.try_get("locale").ok(),
|
||||
premium_since: row.try_get("premium_since").ok(),
|
||||
premium_end: row.try_get("premium_end").ok(),
|
||||
bot: row.try_get("bot").ok(),
|
||||
bot_oauth_scopes: row.try_get("bot_oauth_scopes").ok(),
|
||||
preferences: row.try_get("preferences").ok(),
|
||||
created_at: row.try_get("created_at").ok(),
|
||||
updated_at: row.try_get("updated_at").ok(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ edition = "2024"
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
hex.workspace = true
|
||||
rand = "0.10.0"
|
||||
rand.workspace = true
|
||||
serde.workspace = true
|
||||
serde_with.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
Loading…
Reference in New Issue
Block a user