From 3ee8e52b15085406daafa7bedee7f4343b59bccc Mon Sep 17 00:00:00 2001 From: Vladimir Beskorovainyi Date: Thu, 22 Oct 2026 08:36:57 +0400 Subject: [PATCH 1/3] fix(tool/list-tables): trim whitespace in postgres/cockroachdb table_names filter postgres-list-tables and cockroachdb-list-tables split table_names on comma via string_to_array without trimming, so a value like "t1, t2" became {'t1',' t2'} and the second element never matched, silently omitting the table. Trim each split element before matching, consistent with the mssql and spanner list-tables tools. Fixes #4305 --- .../cockroachdblisttables/cockroachdblisttables.go | 2 +- .../postgres/postgreslisttables/postgreslisttables.go | 2 +- tests/tool.go | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/tools/cockroachdb/cockroachdblisttables/cockroachdblisttables.go b/internal/tools/cockroachdb/cockroachdblisttables/cockroachdblisttables.go index fa093a687866..bb35b3d33d7f 100644 --- a/internal/tools/cockroachdb/cockroachdblisttables/cockroachdblisttables.go +++ b/internal/tools/cockroachdb/cockroachdblisttables/cockroachdblisttables.go @@ -49,7 +49,7 @@ const listTablesStatement = ` CROSS JOIN desired_relkinds dk WHERE t.relkind = ANY(dk.kinds) - AND (NULLIF(TRIM($1), '') IS NULL OR t.relname = ANY(string_to_array($1,','))) + AND (NULLIF(TRIM($1), '') IS NULL OR t.relname IN (SELECT btrim(x) FROM unnest(string_to_array($1,',')) AS x)) AND ns.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast', 'crdb_internal', 'pg_extension') AND ns.nspname NOT LIKE 'pg_temp_%' AND ns.nspname NOT LIKE 'pg_toast_temp_%' ), diff --git a/internal/tools/postgres/postgreslisttables/postgreslisttables.go b/internal/tools/postgres/postgreslisttables/postgreslisttables.go index e8e2e6b7b213..b54175b5e94e 100644 --- a/internal/tools/postgres/postgreslisttables/postgreslisttables.go +++ b/internal/tools/postgres/postgreslisttables/postgreslisttables.go @@ -48,7 +48,7 @@ const listTablesStatement = ` CROSS JOIN desired_relkinds dk WHERE t.relkind = ANY(dk.kinds) -- Filter by selected table relkinds ('r', 'p') - AND (NULLIF(TRIM($1), '') IS NULL OR t.relname = ANY(string_to_array($1,','))) -- $1 is object_names + AND (NULLIF(TRIM($1), '') IS NULL OR t.relname IN (SELECT btrim(x) FROM unnest(string_to_array($1,',')) AS x)) -- $1 is object_names AND ns.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast','google_ml') AND ns.nspname NOT LIKE 'pg_temp_%' AND ns.nspname NOT LIKE 'pg_toast_temp_%' ), diff --git a/tests/tool.go b/tests/tool.go index 48b8e900b86e..9d3ceb18eaf3 100644 --- a/tests/tool.go +++ b/tests/tool.go @@ -1407,6 +1407,13 @@ func RunPostgresListTablesTest(t *testing.T, tableNameParam, tableNameAuth, user wantStatusCode: http.StatusOK, want: fmt.Sprintf("[%s,%s]", getDetailedWant(tableNameAuth, authTableColumns), getDetailedWant(tableNameParam, paramTableColumns)), }, + { + name: "invoke list_tables with multiple table names and surrounding whitespace", + toolName: "list_tables", + args: map[string]any{"table_names": fmt.Sprintf(" %s , %s ", tableNameParam, tableNameAuth)}, + wantStatusCode: http.StatusOK, + want: fmt.Sprintf("[%s,%s]", getDetailedWant(tableNameAuth, authTableColumns), getDetailedWant(tableNameParam, paramTableColumns)), + }, { name: "invoke list_tables with non-existent table", toolName: "list_tables", From 137d767e6b1c000fa61501b22c80e03c5abf1e1b Mon Sep 17 00:00:00 2001 From: Vladimir Beskorovainyi Date: Fri, 23 Oct 2026 14:07:51 +0400 Subject: [PATCH 2/3] refactor(tool/list-tables): use regexp_split_to_array to split postgres table_names Addresses review feedback on the postgres list-tables filter: replace the unnest + btrim subquery with a single regexp_split_to_array(TRIM($1), '\s*,\s*') array operation, which is more idiomatic and also trims any surrounding whitespace, not only spaces. CockroachDB keeps string_to_array + btrim. --- .../tools/postgres/postgreslisttables/postgreslisttables.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/tools/postgres/postgreslisttables/postgreslisttables.go b/internal/tools/postgres/postgreslisttables/postgreslisttables.go index b54175b5e94e..50cbc33a8acf 100644 --- a/internal/tools/postgres/postgreslisttables/postgreslisttables.go +++ b/internal/tools/postgres/postgreslisttables/postgreslisttables.go @@ -48,7 +48,7 @@ const listTablesStatement = ` CROSS JOIN desired_relkinds dk WHERE t.relkind = ANY(dk.kinds) -- Filter by selected table relkinds ('r', 'p') - AND (NULLIF(TRIM($1), '') IS NULL OR t.relname IN (SELECT btrim(x) FROM unnest(string_to_array($1,',')) AS x)) -- $1 is object_names + AND (NULLIF(TRIM($1), '') IS NULL OR t.relname = ANY(regexp_split_to_array(TRIM($1), '\s*,\s*'))) -- $1 is object_names AND ns.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast','google_ml') AND ns.nspname NOT LIKE 'pg_temp_%' AND ns.nspname NOT LIKE 'pg_toast_temp_%' ), From 0e323d46a95037d0725ec9d36304ee477cab5cf6 Mon Sep 17 00:00:00 2001 From: Vladimir Beskorovainyi Date: Fri, 23 Oct 2026 14:12:08 +0400 Subject: [PATCH 3/3] refactor(tool/list-tables): use regexp_split_to_array to split cockroachdb table_names Apply the same single-array split to the CockroachDB query as the Postgres one. regexp_split_to_array is a registered CockroachDB builtin, so this drops the unnest + btrim subquery and trims all surrounding whitespace. --- .../cockroachdb/cockroachdblisttables/cockroachdblisttables.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/tools/cockroachdb/cockroachdblisttables/cockroachdblisttables.go b/internal/tools/cockroachdb/cockroachdblisttables/cockroachdblisttables.go index bb35b3d33d7f..c015a5bfcc45 100644 --- a/internal/tools/cockroachdb/cockroachdblisttables/cockroachdblisttables.go +++ b/internal/tools/cockroachdb/cockroachdblisttables/cockroachdblisttables.go @@ -49,7 +49,7 @@ const listTablesStatement = ` CROSS JOIN desired_relkinds dk WHERE t.relkind = ANY(dk.kinds) - AND (NULLIF(TRIM($1), '') IS NULL OR t.relname IN (SELECT btrim(x) FROM unnest(string_to_array($1,',')) AS x)) + AND (NULLIF(TRIM($1), '') IS NULL OR t.relname = ANY(regexp_split_to_array(TRIM($1), '\s*,\s*'))) AND ns.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast', 'crdb_internal', 'pg_extension') AND ns.nspname NOT LIKE 'pg_temp_%' AND ns.nspname NOT LIKE 'pg_toast_temp_%' ),