diff --git a/compute_tools/src/pg_helpers.rs b/compute_tools/src/pg_helpers.rs index 802e3e93d9..10d8f2c878 100644 --- a/compute_tools/src/pg_helpers.rs +++ b/compute_tools/src/pg_helpers.rs @@ -208,8 +208,8 @@ impl Escaping for PgIdent { /// Here we somewhat mimic the logic of Postgres' `pg_get_functiondef()`, /// fn pg_quote_dollar(&self) -> (String, String) { - let mut tag: String = "".to_string(); - let mut outer_tag = "x".to_string(); + let mut tag: String = "x".to_string(); + let mut outer_tag = "xx".to_string(); // Find the first suitable tag that is not present in the string. // Postgres' max role/DB name length is 63 bytes, so even in the diff --git a/compute_tools/tests/pg_helpers_tests.rs b/compute_tools/tests/pg_helpers_tests.rs index f2d74ff384..b72c1293ee 100644 --- a/compute_tools/tests/pg_helpers_tests.rs +++ b/compute_tools/tests/pg_helpers_tests.rs @@ -64,7 +64,8 @@ test.escaping = 'here''s a backslash \\ and a quote '' and a double-quote " hoor #[test] fn ident_pg_quote_dollar() { let test_cases = vec![ - ("name", ("$$name$$", "x")), + ("name", ("$x$name$x$", "xx")), + ("name$", ("$x$name$$x$", "xx")), ("name$$", ("$x$name$$$x$", "xx")), ("name$$$", ("$x$name$$$$x$", "xx")), ("name$$$$", ("$x$name$$$$$x$", "xx")), diff --git a/test_runner/regress/test_compute_catalog.py b/test_runner/regress/test_compute_catalog.py index 2e7da86d9d..0d3618d1b8 100644 --- a/test_runner/regress/test_compute_catalog.py +++ b/test_runner/regress/test_compute_catalog.py @@ -16,6 +16,9 @@ TEST_ROLE_NAMES = [ {"name": "role \";with ';injections $$ $x$ $ %I !/\\&#@"}, {"name": '"role in double quotes"'}, {"name": "'role in single quotes'"}, + {"name": "role$"}, + {"name": "role$$"}, + {"name": "role$x$"}, ] TEST_DB_NAMES = [ @@ -59,6 +62,18 @@ TEST_DB_NAMES = [ "name": "'db in single quotes'", "owner": "'role in single quotes'", }, + { + "name": "db name$", + "owner": "role$", + }, + { + "name": "db name$$", + "owner": "role$$", + }, + { + "name": "db name$x$", + "owner": "role$x$", + }, ]