use serde::{Deserialize, Deserializer, Serialize};
use serde_json::{ Value as JsonValue};
use std::path::PathBuf;
use crate::DatabaseKind;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct OthersRes<T> {
pub rows_affected: u64,
pub sql: Option<String>,
pub results: Option<Vec<T>>,
}
impl<T> Default for OthersRes<T> {
fn default() -> Self {
Self {
rows_affected: 0,
results: None,
sql: None,
}
}
}
impl<T> OthersRes<T> {
pub fn new(rows_affected: u64) -> Self {
Self {
rows_affected,
results: None,
sql: None,
}
}
pub fn with(data: Vec<T>, rows_affected: usize) -> Self {
Self {
rows_affected: rows_affected as u64,
results: Some(data),
sql: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ColumnBaseInfo {
pub name: String,
#[serde(rename = "type")]
pub r#type: String,
pub index: u64,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SelectRes<T> {
pub results: Vec<T>,
pub length: usize,
pub count: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub sql: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub columns: Option<Vec<ColumnBaseInfo>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub table_name: Option<String>,
}
impl<T> Default for SelectRes<T> {
fn default() -> Self {
Self {
results: Vec::new(),
length: 0,
count: 0,
sql: None,
columns: None,
table_name: None,
}
}
}
impl<T> SelectRes<T> {
pub fn new(
results: Vec<T>,
count: usize,
columns: Option<Vec<ColumnBaseInfo>>,
sql: Option<String>,
) -> Self {
let length = results.len();
Self {
results,
length,
count,
sql,
columns,
table_name: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct SqlRespone {
pub length: u64, pub rows_affected: u64, pub count: u64,
pub results: Option<Vec<JsonValue>>, pub columns: Option<Vec<ColumnBaseInfo>>,
pub is_query: bool,
pub sql: Option<String>,
pub table_name: Option<String>,
}
#[derive(Debug)]
#[cfg_attr(any(feature = "postgres", feature = "mysql", feature = "sqlite"), derive(sqlx::FromRow))]
pub struct DataCount {
pub count: u32,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
#[cfg_attr(any(feature = "postgres", feature = "mysql", feature = "sqlite"), derive(sqlx::FromRow))]
pub struct TableColumn {
pub name: String,
pub ordinal_position: i32, #[serde(rename = "type")]
pub r#type: String,
pub base_type: Option<String>, pub foreign_key_table: Option<String>, pub foreign_key_column: Option<String>,
#[serde(deserialize_with = "bool_or_int_to_bool")]
pub auto_increment: bool, #[serde(deserialize_with = "bool_or_int_to_bool")]
pub not_null: bool, pub dflt_value: Option<String>, #[serde(deserialize_with = "bool_or_int_to_bool")]
pub pk: bool, pub index_name: Option<String>, #[serde(deserialize_with = "bool_or_int_to_bool")]
pub non_unique: bool, pub description: Option<String>, }
fn bool_or_int_to_bool<'de, D>(deserializer: D) -> std::result::Result<bool, D::Error>
where
D: Deserializer<'de>,
{
let v = JsonValue::deserialize(deserializer)?;
match v {
JsonValue::Bool(b) => Ok(b), JsonValue::Number(n) => {
if let Some(i) = n.as_i64() {
match i {
1 => Ok(true),
0 => Ok(false),
_ => Err(serde::de::Error::invalid_value(
serde::de::Unexpected::Signed(i),
&"expected 1 or 0 for boolean value",
)),
}
} else {
Err(serde::de::Error::invalid_type(
serde::de::Unexpected::Other("non-integer number"),
&"expected integer 1 or 0 for boolean value",
))
}
}
_ => Err(serde::de::Error::invalid_type(
serde::de::Unexpected::Other("unexpected value"),
&"expected boolean or integer 1/0",
)),
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DbConnect {
pub kind: DatabaseKind,
#[serde(default = "DbConnect::default_empty")]
pub host: String,
pub port: i64,
#[serde(default = "DbConnect::default_empty")]
pub username: String,
#[serde(default = "DbConnect::default_empty")]
pub password: String,
#[serde(default = "DbConnect::default_empty")]
pub db_name: String,
#[serde(default = "DbConnect::default_empty")]
pub charset: String,
pub ssl_mode: Option<String>,
pub ca_cert: Option<String>,
pub client_cert: Option<String>,
pub client_key: Option<String>,
pub max_connections: Option<i64>,
pub min_connections: Option<i64>,
pub timeout: Option<i64>,
pub service_name: Option<String>,
pub instance: Option<String>,
pub file_dir: PathBuf,
pub file_path: PathBuf,
pub http: Option<String>,
pub region: Option<String>,
pub api: Option<String>,
pub api_token: Option<String>,
}
impl Default for DbConnect {
fn default() -> Self {
Self {
kind: DatabaseKind::Postgres,
host: "127.0.0.1".to_string(),
port: 5432,
username: "postgres".to_string(),
password: "postgres".to_string(),
db_name: "".to_string(),
charset: "".to_string(),
ssl_mode: None,
ca_cert: None,
client_cert: None,
client_key: None,
max_connections: None,
min_connections: None,
timeout: None,
service_name: None,
instance: None,
file_dir: PathBuf::new(),
file_path: PathBuf::new(),
http: None,
region: None,
api: None,
api_token: None,
}
}
}
impl DbConnect {
fn default_empty() -> String {
String::new()
}
pub fn merge_with_changes(&mut self, new_connect: &DbConnect) -> bool {
let mut changed = false;
if self.host != new_connect.host {
self.host = new_connect.host.clone();
changed = true
}
if self.port != new_connect.port {
self.port = new_connect.port;
changed = true
}
if self.username != new_connect.username {
self.username = new_connect.username.clone();
changed = true
}
if self.password != new_connect.password {
self.password = new_connect.password.clone();
changed = true
}
if self.db_name != new_connect.db_name {
self.db_name = new_connect.db_name.clone();
changed = true
}
if self.charset != new_connect.charset {
self.charset = new_connect.charset.clone();
changed = true
}
if self.file_path != new_connect.file_path {
self.file_path = new_connect.file_path.clone();
changed = true
}
if self.file_dir != new_connect.file_dir {
self.file_dir = new_connect.file_dir.clone();
changed = true
}
if self.api != new_connect.api {
self.api = new_connect.api.clone();
changed = true
}
if self.http != new_connect.http {
self.http = new_connect.http.clone();
changed = true
}
changed
}
}
#[derive(Serialize, Debug, Deserialize, PartialEq, Eq, Clone)]
pub struct SchemaInfo {
pub name: String,
pub tables: Vec<TableInfo>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
#[cfg_attr(any(feature = "postgres", feature = "mysql", feature = "sqlite"), derive(sqlx::FromRow))]
pub struct DatabaseInfo {
pub db_name: String,
pub tables: Vec<TableInfo>,
pub schemas: Vec<SchemaInfo>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct TableInfo {
pub table_name: String, #[serde(skip_serializing_if = "Option::is_none")]
pub table_comment: Option<String>,
pub columns: Vec<TableColumn>, pub create_sql: String,
}