Source code for pudl.scripts.pudl_check_fks
"""Check that foreign key constraints in the PUDL database are respected."""
import pathlib
import sys
import click
@click.command(
context_settings={"help_option_names": ["-h", "--help"]},
)
@click.option(
"--logfile",
help="If specified, write logs to this file.",
type=click.Path(
exists=False,
resolve_path=True,
path_type=pathlib.Path,
),
)
@click.option(
"--loglevel",
default="INFO",
type=click.Choice(
["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False
),
)
@click.option(
"--db_path",
help="Path to PUDL SQLite database where foreign keys should be checked.",
type=click.Path(
exists=False,
resolve_path=True,
path_type=pathlib.Path,
),
default=None,
)
[docs]
def main(logfile: pathlib.Path, loglevel: str, db_path: pathlib.Path) -> int:
"""Check that foreign key constraints in the PUDL database are respected.
Dagster manages the dependencies between various assets in our ETL pipeline,
attempting to materialize tables only after their upstream dependencies have been
satisfied. However, this order is non deterministic because they are executed in
parallel, and doesn't necessarily correspond to the foreign-key constraints within
the database, so durint the ETL we disable foreign key constraints within
``pudl.sqlite``.
However, we still expect foreign key constraints to be satisfied once all of the
tables have been loaded, so we check that they are valid after the ETL has
completed. This script runs the same check.
"""
# Deferred to keep --help fast; see pudl/scripts/__init__.py for rationale.
import sqlalchemy as sa # noqa: PLC0415
from dotenv import load_dotenv # noqa: PLC0415
import pudl # noqa: PLC0415
from pudl.validate.integrity import check_foreign_keys # noqa: PLC0415
from pudl.workspace.setup import PudlPaths # noqa: PLC0415
load_dotenv()
# Display logged output from the PUDL package:
pudl.logging_helpers.configure_root_logger(
logfile=str(logfile) if logfile else None,
loglevel=loglevel,
)
# Using PudlPaths to get default value for CLI causes validation issues
if not db_path:
db_uri = PudlPaths().sqlite_db_uri("pudl")
else:
db_uri = f"sqlite:///{db_path}"
check_foreign_keys(sa.create_engine(db_uri))
return 0
if __name__ == "__main__":
sys.exit(main())