def db(connection: Connection) -> Generator:
    transaction = connection.begin()
    session = TestSession(bind=connection)
    try:
        yield session
    finally:
        transaction.rollback()
        session.close()
Esempio n. 2
0
def test_pgsql_db(
        pgsql_connection: Connection,
        request) -> Tuple[SqlLmsOperations, Connection, ConnectionSettings]:
    """
    Fixture that takes the set-up connection and wraps in a transaction. Transaction
    will be rolled-back automatically after each test.

    Returns both a plain transaction-wrapped Connection and a monkey-patched
    SqlLmsOperations that uses that Connection. They may be used interchangeably.
    """
    # Wrap connection in transaction
    transaction: Transaction = pgsql_connection.begin()

    # Rollback transaction in finalizer when test is done
    request.addfinalizer(lambda: transaction.rollback())

    # New version of _exec using our transaction
    def replace_exec(self: SqlLmsOperations, statement: str) -> int:
        result = pgsql_connection.execute(statement)
        if result:
            return int(result.rowcount)
        return 0

    # New version of insert_into_staging using our transaction
    def replace_insert_into_staging(self: SqlLmsOperations, df: DataFrame,
                                    table: str):
        copy = df.copy()
        copy.columns = copy.columns.str.lower()
        copy.to_sql(
            f"stg_{table}",
            con=pgsql_connection,
            schema="lms",
            if_exists="append",
            index=False,
            method="multi",
            chunksize=120,
        )

    # Monkey-patch SqlLmsOperations to use our transaction
    SqlLmsOperations._exec = replace_exec  # type:ignore
    SqlLmsOperations.insert_into_staging = replace_insert_into_staging  # type:ignore

    # Initialize monkey-patched adapter with a dummy engine, doesn't need a real one now
    adapter: SqlLmsOperations = SqlLmsOperations(MagicMock())
    adapter.engine = DbEngine.POSTGRESQL

    return (adapter, pgsql_connection, GetSettings(request))
Esempio n. 3
0
def refresh_and_diff_materialized_view(
    connection: Connection,
    view: Table,
    copy: Table,
    result_columns: Iterable[Column],
) -> Tuple[List[Tuple], List[Tuple], List[Tuple]]:
    """Lock the given `view` with an advisory lock, create a temporary table
    of the view, refresh the view and compute the difference.

    :param connection: A valid SQLAlchemy connection
    :param view: The view to refresh and diff
    :param copy: A temporary table to create and diff
    :param result_columns: The columns to return
    :return: A 3-tuple containing three lists of tuples of the `result_columns`
        of added, deleted and modified records due to the refresh.

    """
    with connection.begin():
        lock_table(connection, view)
        create_temp_copy(connection, view, copy)
        refresh_materialized_view(connection, view)
        return diff_tables(connection, view, copy, result_columns)