Conversation
…IP accepts GRANT OWNERSHIP rejects integration subtype names (SECURITY INTEGRATION, STORAGE INTEGRATION, ...), MATERIALIZED VIEW and HYBRID TABLE. Snowflake names them INTEGRATION, VIEW and TABLE. A plan that transferred ownership of any of these failed at apply with a SQL compilation error, for example: GRANT OWNERSHIP ON SECURITY INTEGRATION X TO ROLE ACCOUNTADMIN COPY CURRENT GRANTS. https://docs.snowflake.com/en/sql-reference/sql/grant-ownership
|
Thanks for the fix. The mapping matches the GRANT OWNERSHIP docs: only
Optional, not blocking: the Generated by Claude Code |
GRANT OWNERSHIP has no EXTERNAL FUNCTION object type, so a transfer away from the default SYSADMIN owner failed with a syntax error. External functions are granted as FUNCTION.
|
Thanks for the review. Both items are done.
One gap remains for external functions. I agree that the shared
|
|
Solid, well-researched fix (the live-account testing against the GRANT OWNERSHIP reference is great). One reuse nit:
Worth extracting to one shared predicate, e.g.: def _is_integration(resource_type) -> bool:
return "INTEGRATION" in str(resource_type)and using it in all four spots. Small, low-risk cleanup, not a blocker. |
What
Snowcap transfers ownership with a
GRANT OWNERSHIPstatement. For four kinds of objects, that statement used an object type that the Snowflake reference does not tell you to use. This PR changestransfer__defaultto use the object type that the reference gives.GRANT OWNERSHIP ON SECURITY INTEGRATION X ...GRANT OWNERSHIP ON INTEGRATION X ...GRANT OWNERSHIP ON MATERIALIZED VIEW X ...GRANT OWNERSHIP ON VIEW X ...GRANT OWNERSHIP ON HYBRID TABLE X ...GRANT OWNERSHIP ON TABLE X ...GRANT OWNERSHIP ON EXTERNAL FUNCTION X ...GRANT OWNERSHIP ON FUNCTION X ...Other resource types do not change.
Why
The
GRANT OWNERSHIPreference gives these rules:INTEGRATION, but no integration subtypes.FUNCTION, but noEXTERNAL FUNCTION. External functions are granted asFUNCTION.GRANT OWNERSHIP ON VIEW."GRANT OWNERSHIP ON TABLE."We tested each form against a live account:
GRANT OWNERSHIP ON SECURITY INTEGRATION ...snowcap applyfailsGRANT OWNERSHIP ON INTEGRATION ...GRANT OWNERSHIP ON MATERIALIZED VIEW ...andON VIEW ...on a real materialized viewGRANT OWNERSHIP ON HYBRID TABLE ...GRANT OWNERSHIP ON EXTERNAL FUNCTION db.sch.fn(VARCHAR) ...GRANT OWNERSHIP ON FUNCTION db.sch.fn(VARCHAR) ...on a name that does not existGRANT OWNERSHIP ON DYNAMIC TABLE,ON ICEBERG TABLE,ON VIEWon a name that does not existSo the integration and external function changes fix real failures. The materialized view and hybrid table changes follow the usage notes. The materialized view change is safe, because Snowflake accepts both forms.
Example: our config declares
ACCOUNTADMINas the owner of a security integration, but a different role owns it in Snowflake. The plan contains a transfer, and the apply fails on this statement:With this fix, Snowcap sends the form that the reference lists:
The fix does not change privilege grants.
GRANT <privilege> ON MATERIALIZED VIEWis valid, socreate_grantkeeps its object types. To find integrations, the fix uses the same test ascreate_grant:"INTEGRATION" in str(resource_type).Known gap: external function names
ExternalFunction.fqnhas no argument types. The UDF classes add them throughudf_fqn. So for a real external function, the transfer is:Snowflake rejects this with error 090208: "Argument types of function must be specified". This PR fixes the object type only. To fix the name,
ExternalFunctionmust identify itself by its signature, which changes how Snowcap matches it to live state. That belongs in a separate PR: #85.Tests
TestTransferResource::test_transfer_uses_snowflake_ownership_object_typehas 12 cases. The 9 mapped cases fail without the fix and pass with it. The 3 neighbor cases (DYNAMIC_TABLE,ICEBERG_TABLE,VIEW) check that the mapping does not grow by accident, for example to "anything that ends in TABLE becomes TABLE".uv run pytest tests/test_lifecycle.py: 143 passed.test_connect_filters_none_valuesfails with and without this change, because it readsSNOWFLAKE_USERfrom the local environment.snowcap planagainst our account gives the same output with this branch and with 1.0.32. The fix changes only the SQL of a transfer, not the plan.