def run_hooks(self, adapter, hook_type, extra_context): nodes = self.manifest.nodes.values() hooks = get_nodes_by_tags(nodes, {hook_type}, NodeType.Operation) ordered_hooks = sorted(hooks, key=lambda h: h.get('index', len(hooks))) for i, hook in enumerate(ordered_hooks): model_name = hook.get('name') # This will clear out an open transaction if there is one. # on-run-* hooks should run outside of a transaction. This happens # b/c psycopg2 automatically begins a transaction when a connection # is created. TODO : Move transaction logic out of here, and # implement a for-loop over these sql statements in jinja-land. # Also, consider configuring psycopg2 (and other adapters?) to # ensure that a transaction is only created if dbt initiates it. adapter.clear_transaction(model_name) compiled = compile_node(adapter, self.config, hook, self.manifest, extra_context) statement = compiled.wrapped_sql hook_index = hook.get('index', len(hooks)) hook_dict = get_hook_dict(statement, index=hook_index) if dbt.flags.STRICT_MODE: Hook(**hook_dict) sql = hook_dict.get('sql', '') if len(sql.strip()) > 0: adapter.execute(sql, model_name=model_name, auto_begin=False, fetch=False) adapter.release_connection(model_name)
def _mangle_hooks(self, config): """Given a config dict that may have `pre-hook`/`post-hook` keys, convert it from the yucky maybe-a-string, maybe-a-dict to a dict. """ # Like most of parsing, this is a horrible hack :( for key in hooks.ModelHookType: if key in config: config[key] = [hooks.get_hook_dict(h) for h in config[key]]
def get_hook_sql(self, adapter, hook, idx, num_hooks, extra_context): compiled = compile_node(adapter, self.config, hook, self.manifest, extra_context) statement = compiled.wrapped_sql hook_index = hook.get('index', num_hooks) hook_dict = get_hook_dict(statement, index=hook_index) if dbt.flags.STRICT_MODE: Hook(**hook_dict) return hook_dict.get('sql', '')
def __pre_deserialize__(cls, data): data = super().__pre_deserialize__(data) field_map = {'post-hook': 'post_hook', 'pre-hook': 'pre_hook'} # create a new dict because otherwise it gets overwritten in # tests new_dict = {} for key in data: new_dict[key] = data[key] data = new_dict for key in hooks.ModelHookType: if key in data: data[key] = [hooks.get_hook_dict(h) for h in data[key]] for field_name in field_map: if field_name in data: new_name = field_map[field_name] data[new_name] = data.pop(field_name) return data
def get_hook(source, index): hook_dict = get_hook_dict(source) hook_dict.setdefault('index', index) return Hook.from_dict(hook_dict)
def from_dict(cls, data, validate=True): for key in hooks.ModelHookType: if key in data: data[key] = [hooks.get_hook_dict(h) for h in data[key]] return super().from_dict(data, validate=validate)