From 204e4a73a2b0d5ab5198c06b63486de325cd94f8 Mon Sep 17 00:00:00 2001 From: fairyfar Date: Tue, 29 Sep 2026 15:39:19 +0800 Subject: [PATCH] Fix get_table_bloat_info and list_user_permissions SQL error of MCP server get_table_bloat_info and list_user_permissions in cbmcp/database.py cannot be used because of some errors(syntax and divide-by-zero). --- mcp-server/src/cbmcp/database.py | 27 ++++++++++++++----------- mcp-server/tests/test_cbmcp.py | 2 +- mcp-server/tests/test_database_tools.py | 5 +---- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/mcp-server/src/cbmcp/database.py b/mcp-server/src/cbmcp/database.py index 6eea1e1bbe4..8735a64b803 100644 --- a/mcp-server/src/cbmcp/database.py +++ b/mcp-server/src/cbmcp/database.py @@ -416,13 +416,15 @@ async def list_user_permissions(self, username: str) -> list[dict]: "n.nspname as schema_name, " "c.relname as object_name, " "c.relkind as object_type, " - "p.perm as permission " + "p.privilege_type as permission " "FROM pg_class c " "JOIN pg_namespace n ON n.oid = c.relnamespace " - "CROSS JOIN LATERAL aclexplode(c.relacl) p " - "WHERE p.grantee = (SELECT oid FROM pg_user WHERE usename = $1) " + "CROSS JOIN LATERAL aclexplode(coalesce(c.relacl, " + "acldefault((CASE WHEN c.relkind = 'S' THEN 's' ELSE 'r' END)::\"char\", c.relowner))) p " + "WHERE p.grantee = (SELECT usesysid FROM pg_user WHERE usename = $1) " + "AND c.relkind IN ('r', 'v', 'm', 'f', 'p', 'S') " "AND n.nspname NOT LIKE 'pg_%' " - "ORDER BY n.nspname, c.relname", + "ORDER BY n.nspname, c.relname, p.privilege_type", username ) return [ @@ -643,15 +645,16 @@ async def get_table_bloat_info(self) -> list[dict]: async with self.get_connection() as conn: records = await conn.fetch( "SELECT " - "schemaname, " - "relname as tablename, " - "pg_size_pretty(pg_total_relation_size(schemaname||'.'||relname)) as total_size, " - "round(100 * (relpages - (relpages * fillfactor / 100)) / relpages, 2) as bloat_ratio " - "FROM pg_class c " + "n.nspname AS schemaname, " + "c.relname AS tablename, " + "pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size, " + "round(100.0 * s.n_dead_tup / GREATEST(s.n_live_tup + s.n_dead_tup, 1), 2)::float8 AS bloat_ratio " + "FROM pg_stat_user_tables s " + "JOIN pg_class c ON c.oid = s.relid " "JOIN pg_namespace n ON n.oid = c.relnamespace " - "JOIN pg_stat_user_tables s ON s.relid = c.oid " - "WHERE c.relkind = 'r' AND n.nspname NOT LIKE 'pg_%' " - "ORDER BY bloat_ratio DESC " + "WHERE c.relkind = 'r' " + "AND n.nspname NOT LIKE 'pg_%' " + "ORDER BY bloat_ratio DESC, n.nspname, c.relname " "LIMIT 20" ) return [ diff --git a/mcp-server/tests/test_cbmcp.py b/mcp-server/tests/test_cbmcp.py index 5560c1d84e6..76b634a6508 100644 --- a/mcp-server/tests/test_cbmcp.py +++ b/mcp-server/tests/test_cbmcp.py @@ -236,7 +236,7 @@ async def test_get_index_usage(self, client): async def test_get_table_bloat_info(self, client): """Test getting table bloat information""" try: - result = await client.call_tool("get_table_bloat_info", {"schema": "public", "limit": 5}) + result = await client.call_tool("get_table_bloat_info", {}) assert result is not None assert hasattr(result, 'structured_content') except Exception as e: diff --git a/mcp-server/tests/test_database_tools.py b/mcp-server/tests/test_database_tools.py index e0fcc644869..30dd4244d48 100644 --- a/mcp-server/tests/test_database_tools.py +++ b/mcp-server/tests/test_database_tools.py @@ -145,10 +145,7 @@ async def test_get_index_usage(self, client): async def test_get_table_bloat_info(self, client): """Test table bloat information""" try: - result = await client.call_tool("get_table_bloat_info", { - "schema": "public", - "limit": 5 - }) + result = await client.call_tool("get_table_bloat_info", {}) assert result is not None assert hasattr(result, 'structured_content') except Exception as e: