fix database tree for postgres

pull/35/head
Takayuki Maeda 3 years ago
parent 4126881b96
commit 8607bbe9a3

@ -82,6 +82,7 @@ impl DatabaseTree {
DatabaseTreeItemKind::Table { table, database } => {
Some((database.clone(), table.clone()))
}
DatabaseTreeItemKind::Schema { .. } => None,
}
})
}
@ -215,7 +216,8 @@ impl DatabaseTree {
.unwrap();
if !up
&& self.selected_item().unwrap().kind().is_database()
&& (self.selected_item().unwrap().kind().is_database()
|| self.selected_item().unwrap().kind().is_schema())
&& self.selected_item().unwrap() == item
{
break;
@ -264,6 +266,11 @@ impl DatabaseTree {
return Some(current_index);
}
if item.kind().is_schema() && !item.kind().is_schema_collapsed() {
self.items.collapse(current_index, false);
return Some(current_index);
}
self.select_parent(current_index)
}
@ -278,6 +285,14 @@ impl DatabaseTree {
return self.selection_updown(current_selection, false);
}
if item.kind().is_schema() {
if item.kind().is_schema_collapsed() {
self.items.expand(current_selection, false);
return Some(current_selection);
}
return self.selection_updown(current_selection, false);
}
None
}
@ -292,8 +307,7 @@ impl DatabaseTree {
#[cfg(test)]
mod test {
use crate::{Database, DatabaseTree, MoveSelection, Table};
// use pretty_assertions::assert_eq;
use crate::{Database, DatabaseTree, MoveSelection, Schema, Table};
use std::collections::BTreeSet;
impl Table {
@ -303,7 +317,17 @@ mod test {
create_time: None,
update_time: None,
engine: None,
table_schema: None,
schema: None,
}
}
fn new_with_schema(name: String, schema: String) -> Self {
Table {
name,
create_time: None,
update_time: None,
engine: None,
schema: Some(schema),
}
}
}
@ -312,11 +336,31 @@ mod test {
fn test_selection() {
let items = vec![Database::new(
"a".to_string(),
vec![Table::new("b".to_string())],
vec![Table::new("b".to_string()).into()],
)];
// a
// b
let mut tree = DatabaseTree::new(&items, &BTreeSet::new()).unwrap();
assert!(tree.move_selection(MoveSelection::Right));
assert_eq!(tree.selection, Some(0));
assert!(tree.move_selection(MoveSelection::Down));
assert_eq!(tree.selection, Some(1));
let items = vec![Database::new(
"a".to_string(),
vec![Schema {
name: "b".to_string(),
tables: vec![Table::new("c".to_string()).into()],
}
.into()],
)];
// a
// b
// c
let mut tree = DatabaseTree::new(&items, &BTreeSet::new()).unwrap();
@ -324,6 +368,10 @@ mod test {
assert_eq!(tree.selection, Some(0));
assert!(tree.move_selection(MoveSelection::Down));
assert_eq!(tree.selection, Some(1));
assert!(tree.move_selection(MoveSelection::Right));
assert_eq!(tree.selection, Some(1));
assert!(tree.move_selection(MoveSelection::Down));
assert_eq!(tree.selection, Some(2));
}
#[test]
@ -331,9 +379,12 @@ mod test {
let items = vec![
Database::new(
"a".to_string(),
vec![Table::new("b".to_string()), Table::new("c".to_string())],
vec![
Table::new("b".to_string()).into(),
Table::new("c".to_string()).into(),
],
),
Database::new("d".to_string(), vec![Table::new("e".to_string())]),
Database::new("d".to_string(), vec![Table::new("e".to_string()).into()]),
];
// a
@ -343,8 +394,38 @@ mod test {
// e
let mut tree = DatabaseTree::new(&items, &BTreeSet::new()).unwrap();
tree.selection = Some(1);
tree.items.collapse(0, false);
assert!(tree.move_selection(MoveSelection::Down));
assert_eq!(tree.selection, Some(3));
let items = vec![
Database::new(
"a".to_string(),
vec![Schema {
name: "b".to_string(),
tables: vec![Table::new("c".to_string()).into()],
}
.into()],
),
Database::new(
"d".to_string(),
vec![Schema {
name: "e".to_string(),
tables: vec![Table::new("f".to_string()).into()],
}
.into()],
),
];
// a
// b
// c
// d
// e
// f
let mut tree = DatabaseTree::new(&items, &BTreeSet::new()).unwrap();
tree.selection = Some(1);
assert!(tree.move_selection(MoveSelection::Down));
@ -355,7 +436,10 @@ mod test {
fn test_selection_left_collapse() {
let items = vec![Database::new(
"a".to_string(),
vec![Table::new("b".to_string()), Table::new("c".to_string())],
vec![
Table::new("b".to_string()).into(),
Table::new("c".to_string()).into(),
],
)];
// a
@ -371,13 +455,52 @@ mod test {
assert!(tree.items.tree_items[0].kind().is_database_collapsed());
assert!(!tree.items.tree_items[1].info().is_visible());
assert!(!tree.items.tree_items[2].info().is_visible());
let items = vec![
Database::new(
"a".to_string(),
vec![Schema {
name: "b".to_string(),
tables: vec![Table::new("c".to_string()).into()],
}
.into()],
),
Database::new(
"d".to_string(),
vec![Schema {
name: "e".to_string(),
tables: vec![Table::new("f".to_string()).into()],
}
.into()],
),
];
// a
// b
// c
// d
// e
// f
let mut tree = DatabaseTree::new(&items, &BTreeSet::new()).unwrap();
tree.selection = Some(0);
tree.items.expand(0, false);
assert!(tree.move_selection(MoveSelection::Left));
assert_eq!(tree.selection, Some(0));
assert!(tree.items.tree_items[0].kind().is_database_collapsed());
assert!(!tree.items.tree_items[1].info().is_visible());
assert!(!tree.items.tree_items[2].info().is_visible());
}
#[test]
fn test_selection_left_parent() {
let items = vec![Database::new(
"a".to_string(),
vec![Table::new("b".to_string()), Table::new("c".to_string())],
vec![
Table::new("b".to_string()).into(),
Table::new("c".to_string()).into(),
],
)];
// a
@ -390,13 +513,43 @@ mod test {
assert!(tree.move_selection(MoveSelection::Left));
assert_eq!(tree.selection, Some(0));
let items = vec![Database::new(
"a".to_string(),
vec![Schema {
name: "b".to_string(),
tables: vec![Table::new_with_schema("c".to_string(), "a".to_string()).into()],
}
.into()],
)];
// a
// b
// c
let mut tree = DatabaseTree::new(&items, &BTreeSet::new()).unwrap();
tree.selection = Some(2);
tree.items.expand(0, false);
tree.items.expand(1, false);
assert!(tree.move_selection(MoveSelection::Left));
assert_eq!(tree.selection, Some(1));
assert!(tree.move_selection(MoveSelection::Left));
assert_eq!(tree.selection, Some(1));
assert!(tree.move_selection(MoveSelection::Left));
assert_eq!(tree.selection, Some(0));
}
#[test]
fn test_selection_right_expand() {
let items = vec![Database::new(
"a".to_string(),
vec![Table::new("b".to_string()), Table::new("c".to_string())],
vec![
Table::new("b".to_string()).into(),
Table::new("c".to_string()).into(),
],
)];
// a
@ -404,7 +557,29 @@ mod test {
// c
let mut tree = DatabaseTree::new(&items, &BTreeSet::new()).unwrap();
tree.selection = Some(0);
assert!(tree.move_selection(MoveSelection::Right));
assert_eq!(tree.selection, Some(0));
assert!(!tree.items.tree_items[0].kind().is_database_collapsed());
assert!(tree.move_selection(MoveSelection::Right));
assert_eq!(tree.selection, Some(1));
let items = vec![Database::new(
"a".to_string(),
vec![Schema {
name: "b".to_string(),
tables: vec![Table::new_with_schema("c".to_string(), "a".to_string()).into()],
}
.into()],
)];
// a
// b
// c
let mut tree = DatabaseTree::new(&items, &BTreeSet::new()).unwrap();
tree.selection = Some(0);
assert!(tree.move_selection(MoveSelection::Right));
@ -413,6 +588,10 @@ mod test {
assert!(tree.move_selection(MoveSelection::Right));
assert_eq!(tree.selection, Some(1));
assert!(tree.move_selection(MoveSelection::Right));
assert_eq!(tree.selection, Some(1));
assert!(!tree.items.tree_items[0].kind().is_schema_collapsed());
}
#[test]
@ -420,9 +599,12 @@ mod test {
let items = vec![
Database::new(
"a".to_string(),
vec![Table::new("b".to_string()), Table::new("c".to_string())],
vec![
Table::new("b".to_string()).into(),
Table::new("c".to_string()).into(),
],
),
Database::new("d".to_string(), vec![Table::new("e".to_string())]),
Database::new("d".to_string(), vec![Table::new("e".to_string()).into()]),
];
// a
@ -438,9 +620,50 @@ mod test {
tree.selection = Some(0);
assert!(tree.move_selection(MoveSelection::Left));
assert!(tree.move_selection(MoveSelection::Down));
assert_eq!(tree.selection, Some(3));
let s = tree.visual_selection().unwrap();
assert_eq!(s.count, 3);
assert_eq!(s.index, 1);
let items = vec![
Database::new(
"a".to_string(),
vec![Schema {
name: "b".to_string(),
tables: vec![Table::new_with_schema("c".to_string(), "a".to_string()).into()],
}
.into()],
),
Database::new(
"d".to_string(),
vec![Schema {
name: "e".to_string(),
tables: vec![Table::new_with_schema("f".to_string(), "d".to_string()).into()],
}
.into()],
),
];
// a
// b
// c
// d
// e
// f
let mut tree = DatabaseTree::new(&items, &BTreeSet::new()).unwrap();
tree.items.expand(0, false);
tree.items.expand(1, false);
tree.items.expand(3, false);
tree.selection = Some(0);
assert!(tree.move_selection(MoveSelection::Left));
assert!(tree.move_selection(MoveSelection::Down));
assert_eq!(tree.selection, Some(3));
let s = tree.visual_selection().unwrap();
assert_eq!(s.count, 4);
assert_eq!(s.index, 1);
}
}

@ -1,6 +1,6 @@
use crate::Database;
use crate::{error::Result, treeitems_iter::TreeItemsIterator};
use crate::{item::DatabaseTreeItemKind, DatabaseTreeItem};
use crate::{Child, Database};
use std::{
collections::{BTreeSet, HashMap},
usize,
@ -51,8 +51,16 @@ impl DatabaseTreeItems {
{
Self::push_databases(e, &mut items, &mut items_added, collapsed)?;
}
for table in &e.tables {
items.push(DatabaseTreeItem::new_table(e, table));
for child in &e.children {
match child {
Child::Table(table) => items.push(DatabaseTreeItem::new_table(e, table)),
Child::Schema(schema) => {
items.push(DatabaseTreeItem::new_schema(e, schema, true));
for table in &schema.tables {
items.push(DatabaseTreeItem::new_table(e, table))
}
}
}
}
}
@ -115,13 +123,37 @@ impl DatabaseTreeItems {
}
}
}
if self.tree_items[index].kind().is_schema() {
self.tree_items[index].collapse_schema();
let name = self.tree_items[index].kind().name();
for i in index + 1..self.tree_items.len() {
let item = &mut self.tree_items[i];
if recursive && item.kind().is_schema() {
item.collapse_schema();
}
if let Some(schema) = item.kind().schema_name() {
if schema == name {
item.hide();
}
} else {
return;
}
}
}
}
pub fn expand(&mut self, index: usize, recursive: bool) {
if self.tree_items[index].kind().is_database() {
self.tree_items[index].expand_database();
let tree_item = self.tree_items[index].clone();
let name = self.tree_items[index].kind().name();
let kind = tree_item.kind();
if recursive {
for i in index + 1..self.tree_items.len() {
@ -139,22 +171,69 @@ impl DatabaseTreeItems {
}
}
self.update_visibility(&Some(name), index + 1, false);
self.update_visibility(kind, index + 1);
}
if self.tree_items[index].kind().is_schema() {
self.tree_items[index].expand_schema();
let tree_item = self.tree_items[index].clone();
let name = self.tree_items[index].kind().name();
let kind = tree_item.kind();
if recursive {
for i in index + 1..self.tree_items.len() {
let item = &mut self.tree_items[i];
if let Some(schema) = item.kind().schema_name() {
if *schema != name {
break;
}
}
if item.kind().is_schema() && item.kind().is_schema_collapsed() {
item.expand_schema();
}
}
}
self.update_visibility(kind, index + 1);
}
}
fn update_visibility(&mut self, prefix: &Option<String>, start_idx: usize, set_defaults: bool) {
let mut inner_collapsed: Option<String> = None;
fn update_visibility(&mut self, prefix: &DatabaseTreeItemKind, start_idx: usize) {
let mut inner_collapsed: Option<DatabaseTreeItemKind> = None;
for i in start_idx..self.tree_items.len() {
if let Some(ref collapsed_item) = inner_collapsed {
if let Some(db) = self.tree_items[i].kind().database_name().clone() {
if db == *collapsed_item {
if set_defaults {
self.tree_items[i].info_mut().set_visible(false);
match collapsed_item {
DatabaseTreeItemKind::Database { name, .. } => {
if let DatabaseTreeItemKind::Schema { database, .. } =
self.tree_items[i].kind().clone()
{
if database.name == *name {
continue;
}
}
if let DatabaseTreeItemKind::Table { database, .. } =
self.tree_items[i].kind().clone()
{
if database.name == *name {
continue;
}
}
continue;
}
DatabaseTreeItemKind::Schema { schema, .. } => {
if let DatabaseTreeItemKind::Table { table, .. } =
self.tree_items[i].kind().clone()
{
if matches!(table.schema, Some(table_schema) if schema.name == table_schema)
{
continue;
}
}
}
_ => (),
}
inner_collapsed = None;
}
@ -162,20 +241,35 @@ impl DatabaseTreeItems {
let item_kind = self.tree_items[i].kind().clone();
if matches!(item_kind, DatabaseTreeItemKind::Database{ collapsed, .. } if collapsed) {
inner_collapsed = item_kind.database_name().clone();
inner_collapsed = Some(item_kind.clone());
} else if matches!(item_kind, DatabaseTreeItemKind::Schema{ collapsed, .. } if collapsed)
{
inner_collapsed = Some(item_kind.clone());
}
if let Some(db) = item_kind.database_name() {
if prefix.as_ref().map_or(true, |prefix| *prefix == *db) {
self.tree_items[i].info_mut().set_visible(true);
match prefix {
DatabaseTreeItemKind::Database { name, .. } => {
if let DatabaseTreeItemKind::Schema { database, .. } = item_kind.clone() {
if *name == database.name {
self.tree_items[i].info_mut().set_visible(true);
}
}
if let DatabaseTreeItemKind::Table { database, .. } = item_kind {
if *name == database.name {
self.tree_items[i].info_mut().set_visible(true);
}
}
}
} else {
// if we do not set defaults we can early out
if set_defaults {
self.tree_items[i].info_mut().set_visible(false);
} else {
return;
DatabaseTreeItemKind::Schema { schema, .. } => {
if let DatabaseTreeItemKind::Table { table, .. } = item_kind {
if matches!(table.schema, Some(table_schema) if schema.name == table_schema)
{
self.tree_items[i].info_mut().set_visible(true);
}
}
}
_ => (),
}
}
}

@ -1,4 +1,4 @@
use crate::{Database, Table};
use crate::{Database, Schema, Table};
#[derive(Debug, Clone)]
pub struct TreeItemInfo {
@ -31,8 +31,19 @@ impl TreeItemInfo {
/// `DatabaseTreeItem` can be of two kinds
#[derive(PartialEq, Debug, Clone)]
pub enum DatabaseTreeItemKind {
Database { name: String, collapsed: bool },
Table { database: Database, table: Table },
Database {
name: String,
collapsed: bool,
},
Table {
database: Database,
table: Table,
},
Schema {
database: Database,
schema: Schema,
collapsed: bool,
},
}
impl DatabaseTreeItemKind {
@ -44,10 +55,23 @@ impl DatabaseTreeItemKind {
matches!(self, Self::Table { .. })
}
pub const fn is_schema(&self) -> bool {
matches!(self, Self::Schema { .. })
}
pub const fn is_database_collapsed(&self) -> bool {
match self {
Self::Database { collapsed, .. } => *collapsed,
Self::Table { .. } => false,
Self::Schema { .. } => false,
}
}
pub const fn is_schema_collapsed(&self) -> bool {
match self {
Self::Database { .. } => false,
Self::Table { .. } => false,
Self::Schema { collapsed, .. } => *collapsed,
}
}
@ -55,6 +79,7 @@ impl DatabaseTreeItemKind {
match self {
Self::Database { name, .. } => name.to_string(),
Self::Table { table, .. } => table.name.clone(),
Self::Schema { schema, .. } => schema.name.clone(),
}
}
@ -62,6 +87,15 @@ impl DatabaseTreeItemKind {
match self {
Self::Database { .. } => None,
Self::Table { database, .. } => Some(database.name.clone()),
Self::Schema { database, .. } => Some(database.name.clone()),
}
}
pub fn schema_name(&self) -> Option<String> {
match self {
Self::Database { .. } => None,
Self::Table { table, .. } => table.schema.clone(),
Self::Schema { .. } => None,
}
}
}
@ -76,7 +110,7 @@ pub struct DatabaseTreeItem {
impl DatabaseTreeItem {
pub fn new_table(database: &Database, table: &Table) -> Self {
Self {
info: TreeItemInfo::new(1, false),
info: TreeItemInfo::new(if table.schema.is_some() { 2 } else { 1 }, false),
kind: DatabaseTreeItemKind::Table {
database: database.clone(),
table: table.clone(),
@ -84,6 +118,17 @@ impl DatabaseTreeItem {
}
}
pub fn new_schema(database: &Database, schema: &Schema, _collapsed: bool) -> Self {
Self {
info: TreeItemInfo::new(1, false),
kind: DatabaseTreeItemKind::Schema {
database: database.clone(),
schema: schema.clone(),
collapsed: true,
},
}
}
pub fn new_database(database: &Database, _collapsed: bool) -> Self {
Self {
info: TreeItemInfo::new(0, true),
@ -133,6 +178,32 @@ impl DatabaseTreeItem {
}
}
pub fn collapse_schema(&mut self) {
if let DatabaseTreeItemKind::Schema {
schema, database, ..
} = &self.kind
{
self.kind = DatabaseTreeItemKind::Schema {
database: database.clone(),
schema: schema.clone(),
collapsed: true,
}
}
}
pub fn expand_schema(&mut self) {
if let DatabaseTreeItemKind::Schema {
schema, database, ..
} = &self.kind
{
self.kind = DatabaseTreeItemKind::Schema {
database: database.clone(),
schema: schema.clone(),
collapsed: false,
};
}
}
pub fn show(&mut self) {
self.info.visible = true;
}
@ -145,6 +216,7 @@ impl DatabaseTreeItem {
match self.kind.clone() {
DatabaseTreeItemKind::Database { name, .. } => name.contains(filter_text),
DatabaseTreeItemKind::Table { table, .. } => table.name.contains(filter_text),
DatabaseTreeItemKind::Schema { schema, .. } => schema.name.contains(filter_text),
}
}

@ -14,18 +14,42 @@ pub use crate::{
#[derive(Clone, PartialEq, Debug)]
pub struct Database {
pub name: String,
pub tables: Vec<Table>,
pub children: Vec<Child>,
}
#[derive(Clone, PartialEq, Debug)]
pub enum Child {
Table(Table),
Schema(Schema),
}
impl From<Table> for Child {
fn from(t: Table) -> Self {
Child::Table(t)
}
}
impl From<Schema> for Child {
fn from(s: Schema) -> Self {
Child::Schema(s)
}
}
impl Database {
pub fn new(database: String, tables: Vec<Table>) -> Self {
pub fn new(database: String, children: Vec<Child>) -> Self {
Self {
name: database,
tables,
children,
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct Schema {
pub name: String,
pub tables: Vec<Table>,
}
#[derive(sqlx::FromRow, Debug, Clone, PartialEq)]
pub struct Table {
#[sqlx(rename = "Name")]
@ -37,5 +61,5 @@ pub struct Table {
#[sqlx(rename = "Engine")]
pub engine: Option<String>,
#[sqlx(default)]
pub table_schema: Option<String>,
pub schema: Option<String>,
}

@ -94,8 +94,8 @@ impl DatabasesComponent {
format!("{:w$}", " ", w = (indent as usize) * 2)
};
let arrow = if item.kind().is_database() {
if item.kind().is_database_collapsed() {
let arrow = if item.kind().is_database() || item.kind().is_schema() {
if item.kind().is_database_collapsed() || item.kind().is_schema_collapsed() {
FOLDER_ICON_COLLAPSED
} else {
FOLDER_ICON_EXPANDED
@ -346,7 +346,7 @@ mod test {
DatabaseTreeItem::new_database(
&Database {
name: "foo".to_string(),
tables: Vec::new(),
children: Vec::new(),
},
false,
),
@ -366,7 +366,7 @@ mod test {
DatabaseTreeItem::new_database(
&Database {
name: "foo".to_string(),
tables: Vec::new(),
children: Vec::new(),
},
false,
),
@ -389,7 +389,7 @@ mod test {
DatabaseTreeItem::new_table(
&Database {
name: "foo".to_string(),
tables: Vec::new(),
children: Vec::new(),
},
&Table {
name: "bar".to_string(),
@ -415,7 +415,7 @@ mod test {
DatabaseTreeItem::new_table(
&Database {
name: "foo".to_string(),
tables: Vec::new(),
children: Vec::new(),
},
&Table {
name: "bar".to_string(),
@ -444,7 +444,7 @@ mod test {
DatabaseTreeItem::new_table(
&Database {
name: "foo".to_string(),
tables: Vec::new(),
children: Vec::new(),
},
&Table {
name: "barbaz".to_string(),
@ -470,7 +470,7 @@ mod test {
DatabaseTreeItem::new_table(
&Database {
name: "foo".to_string(),
tables: Vec::new(),
children: Vec::new(),
},
&Table {
name: "barbaz".to_string(),

@ -5,14 +5,14 @@ pub use mysql::MySqlPool;
pub use postgres::PostgresPool;
use async_trait::async_trait;
use database_tree::{Database, Table};
use database_tree::{Child, Database, Table};
pub const RECORDS_LIMIT_PER_PAGE: u8 = 200;
#[async_trait]
pub trait Pool {
async fn get_databases(&self) -> anyhow::Result<Vec<Database>>;
async fn get_tables(&self, database: String) -> anyhow::Result<Vec<Table>>;
async fn get_tables(&self, database: String) -> anyhow::Result<Vec<Child>>;
async fn get_records(
&self,
database: &Database,

@ -1,7 +1,7 @@
use super::{Pool, RECORDS_LIMIT_PER_PAGE};
use async_trait::async_trait;
use chrono::NaiveDate;
use database_tree::{Database, Table};
use database_tree::{Child, Database, Table};
use futures::TryStreamExt;
use sqlx::mysql::{MySqlColumn, MySqlPool as MPool, MySqlRow};
use sqlx::{Column as _, Row as _, TypeInfo as _};
@ -31,18 +31,22 @@ impl Pool for MySqlPool {
for db in databases {
list.push(Database::new(
db.clone(),
get_tables(db.clone(), &self.pool).await?,
get_tables(db.clone(), &self.pool)
.await?
.into_iter()
.map(|table| table.into())
.collect(),
))
}
Ok(list)
}
async fn get_tables(&self, database: String) -> anyhow::Result<Vec<Table>> {
async fn get_tables(&self, database: String) -> anyhow::Result<Vec<Child>> {
let tables =
sqlx::query_as::<_, Table>(format!("SHOW TABLE STATUS FROM `{}`", database).as_str())
.fetch_all(&self.pool)
.await?;
Ok(tables)
Ok(tables.into_iter().map(|table| table.into()).collect())
}
async fn get_records(

@ -1,8 +1,9 @@
use super::{Pool, RECORDS_LIMIT_PER_PAGE};
use async_trait::async_trait;
use chrono::NaiveDate;
use database_tree::{Database, Table};
use database_tree::{Child, Database, Schema, Table};
use futures::TryStreamExt;
use itertools::Itertools;
use sqlx::postgres::{PgColumn, PgPool, PgRow};
use sqlx::{Column as _, Row as _, TypeInfo as _};
@ -31,13 +32,28 @@ impl Pool for PostgresPool {
for db in databases {
list.push(Database::new(
db.clone(),
get_tables(db.clone(), &self.pool).await?,
vec![Schema {
name: "schema".to_string(),
tables: vec![Table {
name: "table".to_string(),
create_time: None,
update_time: None,
engine: None,
schema: Some("schema".to_string()),
}],
}
.into()],
// get_tables(db.clone(), &self.pool)
// .await?
// .into_iter()
// .map(|table| table.into())
// .collect(),
))
}
Ok(list)
}
async fn get_tables(&self, database: String) -> anyhow::Result<Vec<Table>> {
async fn get_tables(&self, database: String) -> anyhow::Result<Vec<Child>> {
let mut rows = sqlx::query(
"SELECT * FROM information_schema.tables WHERE table_schema='public' and table_catalog = $1",
)
@ -50,10 +66,25 @@ impl Pool for PostgresPool {
create_time: None,
update_time: None,
engine: None,
schema: row.get("table_name"),
schema: row.get("table_schema"),
})
}
Ok(tables)
let mut schemas = vec![];
for (key, group) in &tables.iter().group_by(|t| {
t.schema
.as_ref()
.map(|schema| schema.to_string())
.unwrap_or("".to_string())
}) {
schemas.push(
Schema {
name: key,
tables: group.map(|g| g.clone()).collect(),
}
.into(),
)
}
Ok(schemas)
}
async fn get_records(
@ -137,14 +168,6 @@ impl Pool for PostgresPool {
}
}
pub async fn get_tables(database: String, pool: &PgPool) -> anyhow::Result<Vec<Table>> {
let tables =
sqlx::query_as::<_, Table>(format!("SHOW TABLE STATUS FROM `{}`", database).as_str())
.fetch_all(pool)
.await?;
Ok(tables)
}
fn convert_column_value_to_string(row: &PgRow, column: &PgColumn) -> anyhow::Result<String> {
let column_name = column.name();
match column.type_info().clone().name() {

Loading…
Cancel
Save