Resolvers are used to compare blueprints with existing metadata in Snowflake account and generate DDL commands. DDL commands are suggested or immediately applied using engine, depending on settings. One resolver per object type.

All standard resolvers are located in /resolver/ directory.


All resolvers are derived from AbstractResolver class.

Resolvers for schema objects (TABLE, VIEW, etc.) are derived from AbstractSchemaObjectResolver, which implements additional logic related to "sandbox" schemas and parallel metadata fetching.

Resolver workflow

Internally each resolver implements the following workflow:

  1. Get object blueprints (desired state);

  2. Load existing objects from Snowflake metadata (current state);

  3. Compare full names of blueprints VS full names of existing objects and..

    • "create" new objects;

    • "compare" existing objects;

    • "drop" existing objects without blueprints;

  4. Execute "create" / "compare" / "drop" operations in parallel using ThreadPoolExecutor.

  5. Update caches (if necessary).

Resolve result

Each object may "resolve" in one of the following ways:

  • CREATE - object was created, it did not exist before;

  • ALTER - existing object was updated;

  • DROP - existing object was dropped;

  • REPLACE - existing object was replaced entirely;

  • SKIP - object was not changed, it was skipped;

  • GRANT - grants were updated (used for various types of ROLES);

  • NOCHANGE - object was not changed, did not require any change;

  • ERROR - something went wrong while resolving this object, check logs;

  • UNSUPPORTED - object should be updated, but it is not possible due to lack of Snowflake support for such operation (e.g. converting TRANSIENT schema to normal schema is not possible without full data rewrite);

Resolve result by object name is available in property .resolved_objects.

Intercepted exceptions by object name are available in property .errors.

Methods (base)

  • __init__(engine: SnowDDLEngine) Initialize resolver with engine.

  • get_object_type() Abstract method. Returns object type, which is processed by this resolver.

  • get_blueprints() Abstract method. Returns blueprints to be processed by resolver. Normally it reads blueprints from config, but it may also generate blueprints on the fly based on some other blueprints. For example, "schema roles" are generated automatically based on schema blueprints.

  • get_existing_objects() Abstract method. Returns dict with objects currently existing in Snowflake account. Normally this method calls for SHOW ... metadata commands.

  • create_object(self, bp: AbstractBlueprint) Abstract method. Accepts instance of blueprint. Creates a new object which currently does not exist in Snowflake.

  • compare_object(self, bp: AbstractBlueprint, row: Dict) Abstract method. Accepts blueprint and metadata of existing object. Compares blueprint with existing object and updates or recreates it. Alternatively, it "does nothing" (skip) if object blueprint matches the existing metadata precisely.

  • drop_object(self, row: Dict) Abstract method. Accepts metadata of existing object, which does not have a corresponding blueprint. Drops this object.

Methods (schema objects)

  • get_existing_objects_in_schema(schema: dict) Abstract method. Use it instead of get_existing_objects(). Accepts dict describing schema. Returns dict in the same format as get_existing_objects().


  • .resolved_objects (dict) - resolve result for processed objects;

    • {key} (str) - full name of object;

    • {value} (ResolveResult) - enum value;

  • .errors (dict) - exceptions for processed objects;

    • {key} (str) - full name of object;

    • {value} (Exception) - exception thrown while processing object;

Last updated