コード例 #1
0
    def add_link(self, referenced, dependent):
        """Add a link between two relations to the database. Both the old and
        new entries must already exist in the database.

        The dependent model refers _to_ the referenced model. So, given
        arguments of (jake_test, bar, jake_test, foo):
        both values are in the schema jake_test and foo is a view that refers
        to bar, so "drop bar cascade" will drop foo and all of foo's
        dependents.

        :param DefaultRelation referenced: The referenced model.
        :param DefaultRelation dependent: The dependent model.
        :raises InternalError: If either entry does not exist.
        """
        referenced = _make_key(schema=referenced.schema,
                               identifier=referenced.name)
        if referenced.schema not in self:
            # if we have not cached the referenced schema at all, we must be
            # referring to a table outside our control. There's no need to make
            # a link - we will never drop the referenced relation during a run.
            logger.debug(
                '{dep!s} references {ref!s} but {ref.schema} is not in the '
                'cache, skipping assumed external relation'.format(
                    dep=dependent, ref=referenced))
            return
        dependent = _make_key(schema=dependent.schema,
                              identifier=dependent.name)
        logger.debug('adding link, {!s} references {!s}'.format(
            dependent, referenced))
        with self.lock:
            self._add_link(referenced, dependent)
コード例 #2
0
    def _check_rename_constraints(self, old_key, new_key):
        """Check the rename constraints, and return whether or not the rename
        can proceed.

        If the new key is already present, that is an error.
        If the old key is absent, we debug log and return False, assuming it's
        a temp table being renamed.

        :param _ReferenceKey old_key: The existing key, to rename from.
        :param _ReferenceKey new_key: The new key, to rename to.
        :return bool: If the old relation exists for renaming.
        :raises InternalError: If the new key is already present.
        """
        if new_key in self.relations:
            dbt.exceptions.raise_cache_inconsistent(
                'in rename, new key {} already in cache: {}'
                .format(new_key, list(self.relations.keys()))
            )

        if old_key not in self.relations:
            logger.debug(
                'old key {} not found in self.relations, assuming temporary'
                .format(old_key)
            )
            return False
        return True
コード例 #3
0
ファイル: cache.py プロジェクト: convoyinc/dbt
    def _rename_relation(self, old_key, new_relation):
        """Rename a relation named old_key to new_key, updating references.
        Return whether or not there was a key to rename.

        :param _ReferenceKey old_key: The existing key, to rename from.
        :param _CachedRelation new_key: The new relation, to rename to.
        """
        # On the database level, a rename updates all values that were
        # previously referenced by old_name to be referenced by new_name.
        # basically, the name changes but some underlying ID moves. Kind of
        # like an object reference!
        relation = self.relations.pop(old_key)
        new_key = new_relation.key()

        # relaton has to rename its innards, so it needs the _CachedRelation.
        relation.rename(new_relation)
        # update all the relations that refer to it
        for cached in self.relations.values():
            if cached.is_referenced_by(old_key):
                logger.debug(
                    'updated reference from {0} -> {2} to {1} -> {2}'.format(
                        old_key, new_key, cached.key()))
                cached.rename_key(old_key, new_key)

        self.relations[new_key] = relation
        # also fixup the schemas!
        self.add_schema(new_key.database, new_key.schema)

        return True
コード例 #4
0
ファイル: cache.py プロジェクト: analyst-collective/dbt
    def _rename_relation(self, old_key, new_relation):
        """Rename a relation named old_key to new_key, updating references.
        Return whether or not there was a key to rename.

        :param _ReferenceKey old_key: The existing key, to rename from.
        :param _CachedRelation new_key: The new relation, to rename to.
        """
        # On the database level, a rename updates all values that were
        # previously referenced by old_name to be referenced by new_name.
        # basically, the name changes but some underlying ID moves. Kind of
        # like an object reference!
        relation = self.relations.pop(old_key)
        new_key = new_relation.key()

        # relaton has to rename its innards, so it needs the _CachedRelation.
        relation.rename(new_relation)
        # update all the relations that refer to it
        for cached in self.relations.values():
            if cached.is_referenced_by(old_key):
                logger.debug(
                    'updated reference from {0} -> {2} to {1} -> {2}'
                    .format(old_key, new_key, cached.key())
                )
                cached.rename_key(old_key, new_key)

        self.relations[new_key] = relation
        # also fixup the schemas!
        self.remove_schema(old_key.database, old_key.schema)
        self.add_schema(new_key.database, new_key.schema)

        return True
コード例 #5
0
ファイル: cache.py プロジェクト: analyst-collective/dbt
    def add_link(self, referenced, dependent):
        """Add a link between two relations to the database. Both the old and
        new entries must already exist in the database.

        The dependent model refers _to_ the referenced model. So, given
        arguments of (jake_test, bar, jake_test, foo):
        both values are in the schema jake_test and foo is a view that refers
        to bar, so "drop bar cascade" will drop foo and all of foo's
        dependents.

        :param BaseRelation referenced: The referenced model.
        :param BaseRelation dependent: The dependent model.
        :raises InternalError: If either entry does not exist.
        """
        referenced = _make_key(referenced)
        if (referenced.database, referenced.schema) not in self:
            # if we have not cached the referenced schema at all, we must be
            # referring to a table outside our control. There's no need to make
            # a link - we will never drop the referenced relation during a run.
            logger.debug(
                '{dep!s} references {ref!s} but {ref.database}.{ref.schema} '
                'is not in the cache, skipping assumed external relation'
                .format(dep=dependent, ref=referenced)
            )
            return
        dependent = _make_key(dependent)
        logger.debug(
            'adding link, {!s} references {!s}'.format(dependent, referenced)
        )
        with self.lock:
            self._add_link(referenced, dependent)
コード例 #6
0
ファイル: cache.py プロジェクト: convoyinc/dbt
    def rename(self, old, new):
        """Rename the old schema/identifier to the new schema/identifier and
        update references.

        If the new schema/identifier is already present, that is an error.
        If the schema/identifier key is absent, we only debug log and return,
        assuming it's a temp table being renamed.

        :param BaseRelation old: The existing relation name information.
        :param BaseRelation new: The new relation name information.
        :raises InternalError: If the new key is already present.
        """
        old_key = _make_key(old)
        new_key = _make_key(new)
        logger.debug('Renaming relation {!s} to {!s}'.format(old_key, new_key))

        lazy_log('before rename: {!s}', self.dump_graph)

        with self.lock:
            if self._check_rename_constraints(old_key, new_key):
                self._rename_relation(old_key, _CachedRelation(new))
            else:
                self._setdefault(_CachedRelation(new))

        lazy_log('after rename: {!s}', self.dump_graph)
コード例 #7
0
ファイル: cache.py プロジェクト: convoyinc/dbt
    def _drop_cascade_relation(self, dropped):
        """Drop the given relation and cascade it appropriately to all
        dependent relations.

        :param _CachedRelation dropped: An existing _CachedRelation to drop.
        """
        if dropped not in self.relations:
            logger.debug(
                'dropped a nonexistent relationship: {!s}'.format(dropped))
            return
        consequences = self.relations[dropped].collect_consequences()
        logger.debug('drop {} is cascading to {}'.format(
            dropped, consequences))
        self._remove_refs(consequences)
コード例 #8
0
ファイル: cache.py プロジェクト: convoyinc/dbt
    def drop(self, relation):
        """Drop the named relation and cascade it appropriately to all
        dependent relations.

        Because dbt proactively does many `drop relation if exist ... cascade`
        that are noops, nonexistent relation drops cause a debug log and no
        other actions.

        :param str schema: The schema of the relation to drop.
        :param str identifier: The identifier of the relation to drop.
        """
        dropped = _make_key(relation)
        logger.debug('Dropping relation: {!s}'.format(dropped))
        with self.lock:
            self._drop_cascade_relation(dropped)
コード例 #9
0
ファイル: cache.py プロジェクト: analyst-collective/dbt
    def drop(self, relation):
        """Drop the named relation and cascade it appropriately to all
        dependent relations.

        Because dbt proactively does many `drop relation if exist ... cascade`
        that are noops, nonexistent relation drops cause a debug log and no
        other actions.

        :param str schema: The schema of the relation to drop.
        :param str identifier: The identifier of the relation to drop.
        """
        dropped = _make_key(relation)
        logger.debug('Dropping relation: {!s}'.format(dropped))
        with self.lock:
            self._drop_cascade_relation(dropped)
コード例 #10
0
ファイル: cache.py プロジェクト: analyst-collective/dbt
    def _drop_cascade_relation(self, dropped):
        """Drop the given relation and cascade it appropriately to all
        dependent relations.

        :param _CachedRelation dropped: An existing _CachedRelation to drop.
        """
        if dropped not in self.relations:
            logger.debug('dropped a nonexistent relationship: {!s}'
                         .format(dropped))
            return
        consequences = self.relations[dropped].collect_consequences()
        logger.debug(
            'drop {} is cascading to {}'.format(dropped, consequences)
        )
        self._remove_refs(consequences)
コード例 #11
0
ファイル: cache.py プロジェクト: convoyinc/dbt
    def add(self, relation):
        """Add the relation inner to the cache, under the schema schema and
        identifier identifier

        :param BaseRelation relation: The underlying relation.
        """
        cached = _CachedRelation(relation)
        logger.debug('Adding relation: {!s}'.format(cached))

        lazy_log('before adding: {!s}', self.dump_graph)

        with self.lock:
            self._setdefault(cached)

        lazy_log('after adding: {!s}', self.dump_graph)
コード例 #12
0
ファイル: cache.py プロジェクト: convoyinc/dbt
    def add_link(self, referenced, dependent):
        """Add a link between two relations to the database. If either relation
        does not exist, it will be added as an "external" relation.

        The dependent model refers _to_ the referenced model. So, given
        arguments of (jake_test, bar, jake_test, foo):
        both values are in the schema jake_test and foo is a view that refers
        to bar, so "drop bar cascade" will drop foo and all of foo's
        dependents.

        :param BaseRelation referenced: The referenced model.
        :param BaseRelation dependent: The dependent model.
        :raises InternalError: If either entry does not exist.
        """
        ref_key = _make_key(referenced)
        if (ref_key.database, ref_key.schema) not in self:
            # if we have not cached the referenced schema at all, we must be
            # referring to a table outside our control. There's no need to make
            # a link - we will never drop the referenced relation during a run.
            logger.debug(
                '{dep!s} references {ref!s} but {ref.database}.{ref.schema} '
                'is not in the cache, skipping assumed external relation'.
                format(dep=dependent, ref=ref_key))
            return
        if ref_key not in self.relations:
            # Insert a dummy "external" relation.
            referenced = referenced.replace(
                type=referenced.RelationType.External)
            self.add(referenced)

        dep_key = _make_key(dependent)
        if dep_key not in self.relations:
            # Insert a dummy "external" relation.
            dependent = dependent.replace(
                type=referenced.RelationType.External)
            self.add(dependent)
        logger.debug('adding link, {!s} references {!s}'.format(
            dep_key, ref_key))
        with self.lock:
            self._add_link(ref_key, dep_key)
コード例 #13
0
ファイル: cache.py プロジェクト: analyst-collective/dbt
    def rename(self, old, new):
        """Rename the old schema/identifier to the new schema/identifier and
        update references.

        If the new schema/identifier is already present, that is an error.
        If the schema/identifier key is absent, we only debug log and return,
        assuming it's a temp table being renamed.

        :param BaseRelation old: The existing relation name information.
        :param BaseRelation new: The new relation name information.
        :raises InternalError: If the new key is already present.
        """
        old_key = _make_key(old)
        new_key = _make_key(new)
        logger.debug('Renaming relation {!s} to {!s}'.format(
            old_key, new_key)
        )
        logger.debug('before rename: {}'.format(
            pprint.pformat(self.dump_graph()))
        )

        with self.lock:
            if self._check_rename_constraints(old_key, new_key):
                self._rename_relation(old_key, _CachedRelation(new))
            else:
                self._setdefault(_CachedRelation(new))

        logger.debug('after rename: {}'.format(
            pprint.pformat(self.dump_graph()))
        )
コード例 #14
0
    def _rename_relation(self, old_key, new_key):
        """Rename a relation named old_key to new_key, updating references.
        If the new key is already present, that is an error.
        If the old key is absent, we only debug log and return, assuming it's a
        temp table being renamed.

        :param _ReferenceKey old_key: The existing key, to rename from.
        :param _ReferenceKey new_key: The new key, to rename to.
        :raises InternalError: If the new key is already present.
        """
        if old_key not in self.relations:
            logger.debug(
                'old key {} not found in self.relations, assuming temporary'.
                format(old_key))
            return

        if new_key in self.relations:
            dbt.exceptions.raise_cache_inconsistent(
                'in rename, new key {} already in cache: {}'.format(
                    new_key, list(self.relations.keys())))

        # On the database level, a rename updates all values that were
        # previously referenced by old_name to be referenced by new_name.
        # basically, the name changes but some underlying ID moves. Kind of
        # like an object reference!
        relation = self.relations.pop(old_key)

        relation.rename(new_key)
        # update all the relations that refer to it
        for cached in self.relations.values():
            if cached.is_referenced_by(old_key):
                logger.debug(
                    'updated reference from {0} -> {2} to {1} -> {2}'.format(
                        old_key, new_key, cached.key()))
                cached.rename_key(old_key, new_key)

        self.relations[new_key] = relation
コード例 #15
0
ファイル: cache.py プロジェクト: analyst-collective/dbt
    def add(self, relation):
        """Add the relation inner to the cache, under the schema schema and
        identifier identifier

        :param BaseRelation relation: The underlying relation.
        """
        cached = _CachedRelation(relation)
        logger.debug('Adding relation: {!s}'.format(cached))
        logger.debug('before adding: {}'.format(
            pprint.pformat(self.dump_graph()))
        )
        with self.lock:
            self._setdefault(cached)
        logger.debug('after adding: {}'.format(
            pprint.pformat(self.dump_graph()))
        )
コード例 #16
0
    def rename(self, old, new):
        """Rename the old schema/identifier to the new schema/identifier and
        update references.

        If the new schema/identifier is already present, that is an error.
        If the schema/identifier key is absent, we only debug log and return,
        assuming it's a temp table being renamed.

        :param DefaultRelation old: The existing relation name information.
        :param DefaultRelation new: The new relation name information.
        :raises InternalError: If the new key is already present.
        """
        old_key = _ReferenceKey(schema=old.schema, identifier=old.identifier)
        new_key = _ReferenceKey(schema=new.schema, identifier=new.identifier)
        logger.debug('Renaming relation {!s} to {!s}'.format(old_key, new_key))
        logger.debug('before rename: {}'.format(
            pprint.pformat(self.dump_graph())))
        with self.lock:
            self._rename_relation(old_key, new_key)
        logger.debug('after rename: {}'.format(
            pprint.pformat(self.dump_graph())))
コード例 #17
0
ファイル: cache.py プロジェクト: convoyinc/dbt
def lazy_log(msg, func):
    if logger.disabled:
        return
    logger.debug(msg.format(func()))