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) -> Self { Self {table_name: table_name.into(), columns: Vec::new()} } pub fn col + Type + Clone + 'static>(mut self, column_name: impl Into) -> Self { self.columns.push((column_name.into(), TypeId::of::())); self } pub fn opt_col + Type + Clone + 'static>(mut self, column_name: impl Into) -> Self { self.columns.push((column_name.into(), TypeId::of::>())); self } pub fn arr_col + Type + Clone + 'static>(mut self, column_name: impl Into) -> Self { self.columns.push((column_name.into(), TypeId::of::>())); self } pub fn opt_arr_col + Type + Clone + 'static>(mut self, column_name: impl Into) -> Self { self.columns.push((column_name.into(), TypeId::of::>>())); 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(()) } }