cove-chat/cove-db/src/part/insert.rs
CanadianBaconBoi e27a0d33d7 Initial Commit
2026-02-17 18:22:49 +01:00

75 lines
2.2 KiB
Rust

use std::any::TypeId;
use anyhow::Error;
use sqlx::{Encode, Postgres, Type};
use crate::part::{BindQueryBuilder, SqlPart};
pub struct SqlInsert {
table_name: String,
columns: Vec<(String, TypeId)>
}
impl SqlInsert {
pub fn with_table(table_name: impl Into<String>) -> Self {
Self {table_name: table_name.into(), columns: Vec::new()}
}
pub fn col<T: Encode<'static, Postgres> + Type<Postgres> + Clone + 'static>(mut self, column_name: impl Into<String>) -> Self {
self.columns.push((column_name.into(), TypeId::of::<T>()));
self
}
pub fn opt_col<T: Encode<'static, Postgres> + Type<Postgres> + Clone + 'static>(mut self, column_name: impl Into<String>) -> Self {
self.columns.push((column_name.into(), TypeId::of::<Option<T>>()));
self
}
pub fn arr_col<T: Encode<'static, Postgres> + Type<Postgres> + Clone + 'static>(mut self, column_name: impl Into<String>) -> Self {
self.columns.push((column_name.into(), TypeId::of::<Vec<T>>()));
self
}
pub fn opt_arr_col<T: Encode<'static, Postgres> + Type<Postgres> + Clone + 'static>(mut self, column_name: impl Into<String>) -> Self {
self.columns.push((column_name.into(), TypeId::of::<Option<Vec<T>>>()));
self
}
}
impl SqlPart for SqlInsert {
fn encode(&self, arg_buffer: &mut BindQueryBuilder) -> Result<(), Error> {
arg_buffer.push("INSERT INTO ")
.push(&self.table_name)
.push("(");
let mut cols = vec![];
let mut types = vec![];
for (column_name, column_type) in &self.columns {
cols.push(column_name.as_str());
types.push(column_type.clone());
}
let end_idx = cols.len();
let mut i = 0;
for col in cols {
arg_buffer.push(col);
if i < end_idx-1 {
arg_buffer.push(",");
}
i += 1;
}
arg_buffer.push(") VALUES (");
i = 0;
for ty in types {
unsafe {
arg_buffer.create_bind_raw_unchecked(ty);
}
if i < end_idx-1 {
arg_buffer.push(",");
}
i += 1
}
arg_buffer.push(")");
Ok(())
}
}