Example #1
0
    def get_database_definition(
        self: T, sess: Session, dependencies: Optional[List["ReplaceableEntity"]] = None
    ) -> T:  # $Optional[T]:
        """Creates the entity in the database, retrieves its 'rendered' then rolls it back"""
        with simulate_entity(sess, self, dependencies) as sess:
            # Drop self
            sess.execute(self.to_sql_statement_drop())

            # collect all remaining entities
            db_entities: List[T] = sorted(
                self.from_database(sess, schema=self.schema), key=lambda x: x.identity
            )

        with simulate_entity(sess, self, dependencies) as sess:
            # collect all remaining entities
            all_w_self: List[T] = sorted(
                self.from_database(sess, schema=self.schema), key=lambda x: x.identity
            )

        # Find "self" by diffing the before and after
        for without_self, with_self in zip_longest(db_entities, all_w_self):
            if without_self is None or without_self.identity != with_self.identity:
                return with_self

        raise UnreachableException()
Example #2
0
def solve_resolution_order(sess: Session, entities):
    """Solve for an entity resolution order that increases the probability that
    a migration will suceed if, for example, two new views are created and one
    refers to the other

    This strategy will only solve for simple cases
    """

    resolved = []

    # Resolve the entities with 0 dependencies first (faster)
    logger.info("Resolving entities with no dependencies")
    for entity in entities:
        try:
            with simulate_entity(sess, entity):
                resolved.append(entity)
        except (sqla_exc.ProgrammingError, sqla_exc.InternalError) as exc:
            continue

    # Resolve entities with possible dependencies
    for _ in range(len(entities)):
        logger.info(
            "Resolving entities with dependencies. This may take a minute")
        n_resolved = len(resolved)

        for entity in entities:
            if entity in resolved:
                continue

            try:
                with simulate_entity(sess, entity, dependencies=resolved):
                    resolved.append(entity)
            except (sqla_exc.ProgrammingError, sqla_exc.InternalError):
                continue

        if len(resolved) == n_resolved:
            # No new entities resolved in the last iteration. Exit
            break

    for entity in entities:
        if entity not in resolved:
            resolved.append(entity)

    return resolved
Example #3
0
def test_simulate_entity_shows_user_code_error(sess: Session) -> None:
    sess.execute(TEST_VIEW.to_sql_statement_create())

    with pytest.raises(DataError):
        with simulate_entity(sess, TEST_VIEW):
            # Raises a sql error
            sess.execute("select 1/0").fetchone()

    # Confirm context manager exited gracefully
    assert True