get indexes (#46)

pull/48/head
Takayuki Maeda 3 years ago committed by GitHub
parent 40f5c69a13
commit ae639a3da2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -27,6 +27,7 @@ pub struct App {
column_table: TableComponent,
constraint_table: TableComponent,
foreign_key_table: TableComponent,
index_table: TableComponent,
focus: Focus,
tab: TabComponent,
help: HelpComponent,
@ -47,6 +48,7 @@ impl App {
column_table: TableComponent::new(config.key_config.clone()),
constraint_table: TableComponent::new(config.key_config.clone()),
foreign_key_table: TableComponent::new(config.key_config.clone()),
index_table: TableComponent::new(config.key_config.clone()),
tab: TabComponent::new(config.key_config.clone()),
help: HelpComponent::new(config.key_config.clone()),
databases: DatabasesComponent::new(config.key_config.clone()),
@ -111,6 +113,10 @@ impl App {
right_chunks[1],
matches!(self.focus, Focus::Table),
)?,
Tab::Indexes => {
self.index_table
.draw(f, right_chunks[1], matches!(self.focus, Focus::Table))?
}
}
self.error.draw(f, Rect::default(), false)?;
self.help.draw(f, Rect::default(), false)?;
@ -229,7 +235,7 @@ impl App {
.unwrap()
.get_foreign_keys(&database, &table)
.await?;
if !constraints.is_empty() {
if !foreign_keys.is_empty() {
self.foreign_key_table.update(
foreign_keys
.iter()
@ -240,6 +246,24 @@ impl App {
table.clone(),
);
}
self.index_table.reset();
let indexes = self
.pool
.as_ref()
.unwrap()
.get_indexes(&database, &table)
.await?;
if !indexes.is_empty() {
self.index_table.update(
indexes
.iter()
.map(|c| c.columns())
.collect::<Vec<Vec<String>>>(),
indexes.get(0).unwrap().fields(),
database.clone(),
table.clone(),
);
}
self.table_status
.update(self.record_table.len() as u64, table);
}
@ -397,6 +421,17 @@ impl App {
}
};
}
Tab::Indexes => {
if self.index_table.event(key)?.is_consumed() {
return Ok(EventState::Consumed);
};
if key == self.config.key_config.copy {
if let Some(text) = self.index_table.selected_cells() {
copy_to_clipboard(text.as_str())?
}
};
}
};
}
}

@ -117,6 +117,10 @@ pub fn tab_foreign_keys(key: &KeyConfig) -> CommandText {
)
}
pub fn tab_indexes(key: &KeyConfig) -> CommandText {
CommandText::new(format!("Indexes [{}]", key.tab_indexes), CMD_GROUP_TABLE)
}
pub fn toggle_tabs(key_config: &KeyConfig) -> CommandText {
CommandText::new(
format!(

@ -19,6 +19,7 @@ pub enum Tab {
Columns,
Constraints,
ForeignKeys,
Indexes,
}
impl std::fmt::Display for Tab {
@ -50,6 +51,7 @@ impl TabComponent {
command::tab_columns(&self.key_config).name,
command::tab_constraints(&self.key_config).name,
command::tab_foreign_keys(&self.key_config).name,
command::tab_indexes(&self.key_config).name,
]
}
}
@ -87,6 +89,9 @@ impl Component for TabComponent {
} else if key == self.key_config.tab_foreign_keys {
self.selected_tab = Tab::ForeignKeys;
return Ok(EventState::Consumed);
} else if key == self.key_config.tab_indexes {
self.selected_tab = Tab::Indexes;
return Ok(EventState::Consumed);
}
Ok(EventState::NotConsumed)
}

@ -90,6 +90,7 @@ pub struct KeyConfig {
pub tab_columns: Key,
pub tab_constraints: Key,
pub tab_foreign_keys: Key,
pub tab_indexes: Key,
}
impl Default for KeyConfig {
@ -121,6 +122,7 @@ impl Default for KeyConfig {
tab_columns: Key::Char('2'),
tab_constraints: Key::Char('3'),
tab_foreign_keys: Key::Char('4'),
tab_indexes: Key::Char('5'),
}
}
}

@ -35,6 +35,11 @@ pub trait Pool {
database: &Database,
table: &Table,
) -> anyhow::Result<Vec<Box<dyn TableRow>>>;
async fn get_indexes(
&self,
database: &Database,
table: &Table,
) -> anyhow::Result<Vec<Box<dyn TableRow>>>;
async fn close(&self);
}

@ -108,6 +108,36 @@ impl TableRow for ForeignKey {
}
}
pub struct Index {
name: Option<String>,
column_name: Option<String>,
r#type: Option<String>,
}
impl TableRow for Index {
fn fields(&self) -> Vec<String> {
vec![
"name".to_string(),
"column_name".to_string(),
"type".to_string(),
]
}
fn columns(&self) -> Vec<String> {
vec![
self.name
.as_ref()
.map_or(String::new(), |name| name.to_string()),
self.column_name
.as_ref()
.map_or(String::new(), |column_name| column_name.to_string()),
self.r#type
.as_ref()
.map_or(String::new(), |r#type| r#type.to_string()),
]
}
}
#[async_trait]
impl Pool for MySqlPool {
async fn get_databases(&self) -> anyhow::Result<Vec<Database>> {
@ -271,6 +301,39 @@ impl Pool for MySqlPool {
Ok(foreign_keys)
}
async fn get_indexes(
&self,
database: &Database,
table: &Table,
) -> anyhow::Result<Vec<Box<dyn TableRow>>> {
let mut rows = sqlx::query(
"
SELECT
DISTINCT TABLE_NAME,
INDEX_NAME,
INDEX_TYPE,
COLUMN_NAME
FROM
INFORMATION_SCHEMA.STATISTICS
WHERE
TABLE_SCHEMA = ?
AND TABLE_NAME = ?
",
)
.bind(&database.name)
.bind(&table.name)
.fetch(&self.pool);
let mut foreign_keys: Vec<Box<dyn TableRow>> = vec![];
while let Some(row) = rows.try_next().await? {
foreign_keys.push(Box::new(Index {
name: row.try_get("INDEX_NAME")?,
column_name: row.try_get("COLUMN_NAME")?,
r#type: row.try_get("INDEX_TYPE")?,
}))
}
Ok(foreign_keys)
}
async fn close(&self) {
self.pool.close().await;
}

@ -109,6 +109,36 @@ impl TableRow for ForeignKey {
}
}
pub struct Index {
name: Option<String>,
column_name: Option<String>,
r#type: Option<String>,
}
impl TableRow for Index {
fn fields(&self) -> Vec<String> {
vec![
"name".to_string(),
"column_name".to_string(),
"type".to_string(),
]
}
fn columns(&self) -> Vec<String> {
vec![
self.name
.as_ref()
.map_or(String::new(), |name| name.to_string()),
self.column_name
.as_ref()
.map_or(String::new(), |column_name| column_name.to_string()),
self.r#type
.as_ref()
.map_or(String::new(), |r#type| r#type.to_string()),
]
}
}
#[async_trait]
impl Pool for PostgresPool {
async fn get_databases(&self) -> anyhow::Result<Vec<Database>> {
@ -338,6 +368,50 @@ impl Pool for PostgresPool {
Ok(constraints)
}
async fn get_indexes(
&self,
_database: &Database,
table: &Table,
) -> anyhow::Result<Vec<Box<dyn TableRow>>> {
let mut rows = sqlx::query(
"
SELECT
t.relname AS table_name,
i.relname AS index_name,
a.attname AS column_name,
am.amname AS type
FROM
pg_class t,
pg_class i,
pg_index ix,
pg_attribute a,
pg_am am
WHERE
t.oid = ix.indrelid
and i.oid = ix.indexrelid
and a.attrelid = t.oid
and a.attnum = ANY(ix.indkey)
and t.relkind = 'r'
and am.oid = i.relam
and t.relname = $1
ORDER BY
t.relname,
i.relname
",
)
.bind(&table.name)
.fetch(&self.pool);
let mut foreign_keys: Vec<Box<dyn TableRow>> = vec![];
while let Some(row) = rows.try_next().await? {
foreign_keys.push(Box::new(Index {
name: row.try_get("index_name")?,
column_name: row.try_get("column_name")?,
r#type: row.try_get("type")?,
}))
}
Ok(foreign_keys)
}
async fn close(&self) {
self.pool.close().await;
}

Loading…
Cancel
Save