feat(schema): show table properties in object browser
This commit is contained in:
22 files changed
+284
-12
No files matched your search
@@ -1873,6 +1873,7 @@ fn oracle_object_statistics_from_query_result(result: db::QueryResult) -> Vec<db
|
||||
schema: query_result_cell_string(&row, 1),
|
||||
estimated_rows: query_result_cell_i64(&row, 2),
|
||||
total_bytes: query_result_cell_i64(&row, 3),
|
||||
..Default::default()
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
@@ -6376,7 +6377,10 @@ async fn list_object_statistics_once(
|
||||
if *mode == MysqlMode::OceanBaseOracle || db_config.as_ref().is_some_and(db::manticoresearch::is_config) {
|
||||
Ok(vec![])
|
||||
} else {
|
||||
db::mysql::list_object_statistics(p, database).await
|
||||
let include_mysql_details = db_config.as_ref().is_some_and(|config| {
|
||||
config.db_type == DatabaseType::Mysql && !db::mysql_compatible::uses_show_metadata(config)
|
||||
});
|
||||
db::mysql::list_object_statistics(p, database, include_mysql_details).await
|
||||
}
|
||||
}
|
||||
PoolKind::Postgres(p) if db_config.as_ref().is_some_and(is_questdb_config) => Ok(vec![]),
|
||||
|
||||
@@ -554,6 +554,7 @@ fn clickhouse_object_statistics_from_row(row: &[serde_json::Value], database: &s
|
||||
schema: Some(database.to_string()),
|
||||
estimated_rows: json_value_as_i64(row.get(1)),
|
||||
total_bytes: json_value_as_i64(row.get(2)),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -321,6 +321,7 @@ pub fn object_statistics_from_collection_stats(name: &str, database: &str, resul
|
||||
(None, None) => None,
|
||||
(data, index) => Some(data.unwrap_or(0).saturating_add(index.unwrap_or(0))),
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3820,10 +3820,18 @@ pub async fn list_objects_with_logical_tables(
|
||||
Ok(PagedObjectList { objects, paging_applied })
|
||||
}
|
||||
|
||||
pub async fn list_object_statistics(pool: &MySqlPool, database: &str) -> Result<Vec<ObjectStatistics>, String> {
|
||||
pub async fn list_object_statistics(
|
||||
pool: &MySqlPool,
|
||||
database: &str,
|
||||
include_mysql_details: bool,
|
||||
) -> Result<Vec<ObjectStatistics>, String> {
|
||||
let columns = if include_mysql_details {
|
||||
"TABLE_NAME, TABLE_ROWS, DATA_LENGTH, ENGINE, CREATE_TIME, UPDATE_TIME, TABLE_COLLATION, ROW_FORMAT, AVG_ROW_LENGTH, MAX_DATA_LENGTH, CHECK_TIME, INDEX_LENGTH, AUTO_INCREMENT, DATA_FREE, COALESCE(DATA_LENGTH, 0) + COALESCE(INDEX_LENGTH, 0) AS TOTAL_BYTES"
|
||||
} else {
|
||||
"TABLE_NAME, TABLE_ROWS, COALESCE(DATA_LENGTH, 0) + COALESCE(INDEX_LENGTH, 0) AS TOTAL_BYTES"
|
||||
};
|
||||
let sql = format!(
|
||||
"SELECT TABLE_NAME, TABLE_ROWS, COALESCE(DATA_LENGTH, 0) + COALESCE(INDEX_LENGTH, 0) AS TOTAL_BYTES \
|
||||
FROM information_schema.TABLES \
|
||||
"SELECT {columns} FROM information_schema.TABLES \
|
||||
WHERE TABLE_SCHEMA = {} AND TABLE_TYPE <> 'VIEW' \
|
||||
ORDER BY TABLE_NAME",
|
||||
quote_value(database),
|
||||
@@ -3838,12 +3846,31 @@ pub async fn list_object_statistics(pool: &MySqlPool, database: &str) -> Result<
|
||||
.iter()
|
||||
.filter_map(|row| {
|
||||
let name = get_str_by_name(row, "TABLE_NAME").trim().to_string();
|
||||
(!name.is_empty()).then_some(ObjectStatistics {
|
||||
if name.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut statistics = ObjectStatistics {
|
||||
name,
|
||||
schema: Some(database.to_string()),
|
||||
estimated_rows: get_opt_i64(row, "TABLE_ROWS"),
|
||||
total_bytes: get_opt_i64(row, "TOTAL_BYTES"),
|
||||
})
|
||||
..Default::default()
|
||||
};
|
||||
if include_mysql_details {
|
||||
statistics.data_length = get_opt_i64(row, "DATA_LENGTH");
|
||||
statistics.engine = get_opt_str(row, "ENGINE");
|
||||
statistics.created_at = get_opt_metadata_string(row, "CREATE_TIME");
|
||||
statistics.updated_at = get_opt_metadata_string(row, "UPDATE_TIME");
|
||||
statistics.collation = get_opt_str(row, "TABLE_COLLATION");
|
||||
statistics.row_format = get_opt_str(row, "ROW_FORMAT");
|
||||
statistics.avg_row_length = get_opt_i64(row, "AVG_ROW_LENGTH");
|
||||
statistics.max_data_length = get_opt_i64(row, "MAX_DATA_LENGTH");
|
||||
statistics.check_time = get_opt_metadata_string(row, "CHECK_TIME");
|
||||
statistics.index_length = get_opt_i64(row, "INDEX_LENGTH");
|
||||
statistics.auto_increment = get_opt_unsigned_metadata_string(row, "AUTO_INCREMENT");
|
||||
statistics.data_free = get_opt_i64(row, "DATA_FREE");
|
||||
}
|
||||
Some(statistics)
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
@@ -7248,6 +7248,7 @@ pub async fn list_object_statistics(pool: &Pool, schema: &str) -> Result<Vec<Obj
|
||||
schema: Some(schema.to_string()),
|
||||
estimated_rows: row.try_get::<_, i64>(1).ok(),
|
||||
total_bytes: row.try_get::<_, i64>(2).ok(),
|
||||
..Default::default()
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
@@ -2836,6 +2836,7 @@ pub async fn list_object_statistics(
|
||||
.ok()
|
||||
.flatten()
|
||||
.or_else(|| row.try_get::<i32, _>(2).ok().flatten().map(i64::from)),
|
||||
..Default::default()
|
||||
})
|
||||
.filter(|stat| !stat.name.is_empty())
|
||||
.collect())
|
||||
|
||||
@@ -270,6 +270,7 @@ pub async fn list_object_statistics(client: &VictoriaMetricsClient) -> Result<Ve
|
||||
estimated_rows: item.value.as_i64().or_else(|| item.value.as_str().and_then(|value| value.parse().ok())),
|
||||
// VictoriaMetrics exposes series counts here, but no per-metric storage size.
|
||||
total_bytes: None,
|
||||
..Default::default()
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
@@ -442,7 +442,7 @@ mod tests {
|
||||
async fn http_inactivity_expiry_rolls_back_and_disconnects_inner_owner() {
|
||||
let backend = Arc::new(HttpTestBackend::new());
|
||||
let (url, manager, cancellation, server_task) =
|
||||
start_http_test_server(backend.clone(), std::time::Duration::from_millis(50)).await;
|
||||
start_http_test_server(backend.clone(), std::time::Duration::from_millis(500)).await;
|
||||
let (client, _) = open_active_transaction(&url).await;
|
||||
|
||||
wait_for_disposal(&backend).await;
|
||||
|
||||
@@ -145,12 +145,36 @@ pub struct ExtensionInfo {
|
||||
pub schema: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct ObjectStatistics {
|
||||
pub name: String,
|
||||
pub schema: Option<String>,
|
||||
pub estimated_rows: Option<i64>,
|
||||
pub total_bytes: Option<i64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub data_length: Option<i64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub engine: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub created_at: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub updated_at: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub collation: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub row_format: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub avg_row_length: Option<i64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub max_data_length: Option<i64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub check_time: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub index_length: Option<i64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub auto_increment: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub data_free: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
|
||||
Reference in new issue
Block a user