return TableRow

pull/41/head
Takayuki Maeda 3 years ago
parent 07e7a5846a
commit 7bb42a91cc

@ -1,8 +1,6 @@
use crate::clipboard::copy_to_clipboard;
use crate::components::{CommandInfo, Component as _, DrawableComponent as _, EventState};
use crate::database::{
Column, Constraint as TConstraint, MySqlPool, Pool, PostgresPool, RECORDS_LIMIT_PER_PAGE,
};
use crate::database::{MySqlPool, Pool, PostgresPool, RECORDS_LIMIT_PER_PAGE};
use crate::event::Key;
use crate::{
components::tab::Tab,
@ -188,16 +186,17 @@ impl App {
.unwrap()
.get_columns(&database, &table)
.await?;
self.column_table.update(
columns
.iter()
.map(|c| c.columns())
.collect::<Vec<Vec<String>>>(),
Column::headers(),
database.clone(),
table.clone(),
);
if !columns.is_empty() {
self.column_table.update(
columns
.iter()
.map(|c| c.columns())
.collect::<Vec<Vec<String>>>(),
columns.get(0).unwrap().fields(),
database.clone(),
table.clone(),
);
}
self.constraint_table.reset();
let constraints = self
.pool
@ -205,15 +204,17 @@ impl App {
.unwrap()
.get_constraints(&database, &table)
.await?;
self.constraint_table.update(
constraints
.iter()
.map(|c| c.columns())
.collect::<Vec<Vec<String>>>(),
TConstraint::headers(),
database.clone(),
table.clone(),
);
if !constraints.is_empty() {
self.constraint_table.update(
constraints
.iter()
.map(|c| c.columns())
.collect::<Vec<Vec<String>>>(),
constraints.get(0).unwrap().fields(),
database.clone(),
table.clone(),
);
}
self.table_status
.update(self.record_table.len() as u64, table);
}

@ -20,26 +20,20 @@ pub trait Pool {
page: u16,
filter: Option<String>,
) -> anyhow::Result<(Vec<String>, Vec<Vec<String>>)>;
async fn get_columns(&self, database: &Database, table: &Table) -> anyhow::Result<Vec<Column>>;
async fn get_columns(
&self,
database: &Database,
table: &Table,
) -> anyhow::Result<Vec<Box<dyn TableRow>>>;
async fn get_constraints(
&self,
database: &Database,
table: &Table,
) -> anyhow::Result<Vec<Constraint>>;
) -> anyhow::Result<Vec<Box<dyn TableRow>>>;
async fn close(&self);
}
pub struct Constraint {
name: String,
column_name: String,
}
impl Constraint {
pub fn headers() -> Vec<String> {
vec!["name".to_string(), "column_name".to_string()]
}
pub fn columns(&self) -> Vec<String> {
vec![self.name.to_string(), self.column_name.to_string()]
}
pub trait TableRow: std::marker::Send {
fn fields(&self) -> Vec<String>;
fn columns(&self) -> Vec<String>;
}

@ -1,4 +1,4 @@
use super::{Column, Constraint, Pool, RECORDS_LIMIT_PER_PAGE};
use super::{Pool, TableRow, RECORDS_LIMIT_PER_PAGE};
use async_trait::async_trait;
use chrono::NaiveDate;
use database_tree::{Child, Database, Table};
@ -18,6 +18,61 @@ impl MySqlPool {
}
}
pub struct Constraint {
name: String,
column_name: String,
}
impl TableRow for Constraint {
fn fields(&self) -> Vec<String> {
vec!["name".to_string(), "column_name".to_string()]
}
fn columns(&self) -> Vec<String> {
vec![self.name.to_string(), self.column_name.to_string()]
}
}
pub struct Column {
name: Option<String>,
r#type: Option<String>,
null: Option<String>,
default: Option<String>,
comment: Option<String>,
}
impl TableRow for Column {
fn fields(&self) -> Vec<String> {
vec![
"name".to_string(),
"type".to_string(),
"null".to_string(),
"default".to_string(),
"comment".to_string(),
]
}
fn columns(&self) -> Vec<String> {
vec![
self.name
.as_ref()
.map_or(String::new(), |name| name.to_string()),
self.r#type
.as_ref()
.map_or(String::new(), |r#type| r#type.to_string()),
self.null
.as_ref()
.map_or(String::new(), |null| null.to_string()),
self.default
.as_ref()
.map_or(String::new(), |default| default.to_string()),
self.comment
.as_ref()
.map_or(String::new(), |comment| comment.to_string()),
]
}
}
#[async_trait]
impl Pool for MySqlPool {
async fn get_databases(&self) -> anyhow::Result<Vec<Database>> {
@ -88,21 +143,25 @@ impl Pool for MySqlPool {
Ok((headers, records))
}
async fn get_columns(&self, database: &Database, table: &Table) -> anyhow::Result<Vec<Column>> {
async fn get_columns(
&self,
database: &Database,
table: &Table,
) -> anyhow::Result<Vec<Box<dyn TableRow>>> {
let query = format!(
"SHOW FULL COLUMNS FROM `{}`.`{}`",
database.name, table.name
);
let mut rows = sqlx::query(query.as_str()).fetch(&self.pool);
let mut columns = vec![];
let mut columns: Vec<Box<dyn TableRow>> = vec![];
while let Some(row) = rows.try_next().await? {
columns.push(Column {
columns.push(Box::new(Column {
name: row.try_get("Field")?,
r#type: row.try_get("Type")?,
null: row.try_get("Null")?,
default: row.try_get("Default")?,
comment: row.try_get("Comment")?,
})
}))
}
Ok(columns)
}
@ -111,7 +170,7 @@ impl Pool for MySqlPool {
&self,
database: &Database,
table: &Table,
) -> anyhow::Result<Vec<Constraint>> {
) -> anyhow::Result<Vec<Box<dyn TableRow>>> {
let mut rows = sqlx::query(
"
SELECT
@ -127,12 +186,12 @@ impl Pool for MySqlPool {
.bind(&database.name)
.bind(&table.name)
.fetch(&self.pool);
let mut constraints = vec![];
let mut constraints: Vec<Box<dyn TableRow>> = vec![];
while let Some(row) = rows.try_next().await? {
constraints.push(Constraint {
constraints.push(Box::new(Constraint {
name: row.try_get("CONSTRAINT_NAME")?,
column_name: row.try_get("COLUMN_NAME")?,
})
}))
}
Ok(constraints)
}

@ -1,4 +1,4 @@
use super::{Column, Constraint, Pool, RECORDS_LIMIT_PER_PAGE};
use super::{Pool, TableRow, RECORDS_LIMIT_PER_PAGE};
use async_trait::async_trait;
use chrono::NaiveDate;
use database_tree::{Child, Database, Schema, Table};
@ -19,6 +19,61 @@ impl PostgresPool {
}
}
pub struct Constraint {
name: String,
column_name: String,
}
impl TableRow for Constraint {
fn fields(&self) -> Vec<String> {
vec!["name".to_string(), "column_name".to_string()]
}
fn columns(&self) -> Vec<String> {
vec![self.name.to_string(), self.column_name.to_string()]
}
}
pub struct Column {
name: Option<String>,
r#type: Option<String>,
null: Option<String>,
default: Option<String>,
comment: Option<String>,
}
impl TableRow for Column {
fn fields(&self) -> Vec<String> {
vec![
"name".to_string(),
"type".to_string(),
"null".to_string(),
"default".to_string(),
"comment".to_string(),
]
}
fn columns(&self) -> Vec<String> {
vec![
self.name
.as_ref()
.map_or(String::new(), |name| name.to_string()),
self.r#type
.as_ref()
.map_or(String::new(), |r#type| r#type.to_string()),
self.null
.as_ref()
.map_or(String::new(), |null| null.to_string()),
self.default
.as_ref()
.map_or(String::new(), |default| default.to_string()),
self.comment
.as_ref()
.map_or(String::new(), |comment| comment.to_string()),
]
}
}
#[async_trait]
impl Pool for PostgresPool {
async fn get_databases(&self) -> anyhow::Result<Vec<Database>> {
@ -143,7 +198,11 @@ impl Pool for PostgresPool {
Ok((headers, records))
}
async fn get_columns(&self, database: &Database, table: &Table) -> anyhow::Result<Vec<Column>> {
async fn get_columns(
&self,
database: &Database,
table: &Table,
) -> anyhow::Result<Vec<Box<dyn TableRow>>> {
let table_schema = table
.schema
.as_ref()
@ -153,15 +212,15 @@ impl Pool for PostgresPool {
)
.bind(&database.name).bind(table_schema).bind(&table.name)
.fetch(&self.pool);
let mut columns = vec![];
let mut columns: Vec<Box<dyn TableRow>> = vec![];
while let Some(row) = rows.try_next().await? {
columns.push(Column {
columns.push(Box::new(Column {
name: row.try_get("column_name")?,
r#type: row.try_get("data_type")?,
null: row.try_get("is_nullable")?,
default: row.try_get("column_default")?,
comment: row.try_get("Comment")?,
})
}))
}
Ok(columns)
}
@ -170,7 +229,7 @@ impl Pool for PostgresPool {
&self,
_database: &Database,
table: &Table,
) -> anyhow::Result<Vec<Constraint>> {
) -> anyhow::Result<Vec<Box<dyn TableRow>>> {
let mut rows = sqlx::query(
"
SELECT
@ -188,12 +247,12 @@ impl Pool for PostgresPool {
)
.bind(&table.name)
.fetch(&self.pool);
let mut constraints = vec![];
let mut constraints: Vec<Box<dyn TableRow>> = vec![];
while let Some(row) = rows.try_next().await? {
constraints.push(Constraint {
constraints.push(Box::new(Constraint {
name: row.try_get("constraint_name")?,
column_name: row.try_get("column_name")?,
})
}))
}
Ok(constraints)
}

Loading…
Cancel
Save