Skip to content

Commit 7673d44

Browse files
def-claude
andcommitted
dbt-materialize: quote the schema when copying default privileges
`internal_copy_schema_default_privs` interpolated the target schema name raw into `ALTER DEFAULT PRIVILEGES ... IN SCHEMA`, so the parser folded it to lowercase. #38066 started creating the deployment schema with a quoted name, which made the two disagree for any schema name that is not a bare lowercase identifier: `deploy_init` created `"Prod_dbt_deploy"` and then failed trying to alter default privileges in `prod_dbt_deploy`, after the schema already existed. The retry then took the schema-already-exists branch, which skips both privilege-copying macros, so the operation reported success while silently dropping the grants and default privileges the production schema had. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 4260c34 commit 7673d44

3 files changed

Lines changed: 12 additions & 7 deletions

File tree

‎misc/dbt-materialize/CHANGELOG.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
* Fix `deploy_init` when the `CI_TAG` environment variable is set. The
1111
deployment schema was tagged without passing the schema name, so the
1212
operation failed with `COMMENT ON SCHEMA ""`. The deployment schema is
13-
now also created with a quoted name, matching how it is dropped.
13+
now also created with a quoted name, matching how it is dropped and how its
14+
grants and default privileges are copied.
1415

1516
## 1.9.11 - 2026-07-26
1617

‎misc/dbt-materialize/dbt/include/materialize/macros/deploy/deploy_init.sql‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ SELECT
170170
WHEN object_owner = 'PUBLIC' THEN 'FOR ALL ROLES '
171171
ELSE 'FOR ROLE ' || quote_ident(object_owner) || ' '
172172
END ||
173-
'IN SCHEMA {{ to }} ' ||
173+
'IN SCHEMA ' || quote_ident({{ dbt.string_literal(to) }}) || ' ' ||
174174
'GRANT ' || privilege_type || ' ' ||
175175
'ON ' || object_type || 's ' ||
176176
CASE

‎misc/dbt-materialize/tests/adapter/test_deploy.py‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,18 @@ def cleanup(self, project):
6464
project.run_sql("DROP ROLE IF EXISTS my_role")
6565
project.run_sql("DROP SCHEMA IF EXISTS blue_schema CASCADE")
6666
project.run_sql("DROP SCHEMA IF EXISTS green_schema CASCADE")
67+
project.run_sql('DROP SCHEMA IF EXISTS "Green_Schema" CASCADE')
6768
project.run_sql("DROP CLUSTER IF EXISTS blue_cluster CASCADE")
6869
project.run_sql("DROP CLUSTER IF EXISTS green_cluster CASCADE")
6970

70-
def test_apply_schema_default_privileges(self, project):
71+
# `deploy_init` creates the deployment schema with a quoted name, so a
72+
# non-lowercase name has to survive into the generated statements too.
73+
@pytest.mark.parametrize("to_schema", ["green_schema", "Green_Schema"])
74+
def test_apply_schema_default_privileges(self, project, to_schema):
7175
project.run_sql("CREATE ROLE my_role")
7276
project.run_sql("GRANT my_role TO materialize")
7377
project.run_sql("CREATE SCHEMA blue_schema")
74-
project.run_sql("CREATE SCHEMA green_schema")
78+
project.run_sql(f'CREATE SCHEMA "{to_schema}"')
7579
project.run_sql(
7680
"ALTER DEFAULT PRIVILEGES FOR ROLE my_role IN SCHEMA blue_schema GRANT SELECT ON TABLES TO my_role"
7781
)
@@ -81,15 +85,15 @@ def test_apply_schema_default_privileges(self, project):
8185
"run-operation",
8286
"internal_copy_schema_default_privs",
8387
"--args",
84-
"{from: blue_schema, to: green_schema}",
88+
f"{{from: blue_schema, to: {to_schema}}}",
8589
]
8690
)
8791

8892
result = project.run_sql(
89-
"""SELECT count(*) = 1
93+
f"""SELECT count(*) = 1
9094
FROM mz_internal.mz_show_default_privileges
9195
WHERE database = current_database()
92-
AND schema = 'green_schema'
96+
AND schema = '{to_schema}'
9397
AND grantee = 'my_role'
9498
AND object_type = 'table'
9599
AND privilege_type = 'SELECT'""",

0 commit comments

Comments
 (0)