diff --git a/documentations/Ergebnisse/Abschlussbericht_und_Praesentation/PhHo/4-4-2-database-generator.md b/documentations/Ergebnisse/Abschlussbericht_und_Praesentation/PhHo/4-4-2-database-generator.md index c316059..ea862a1 100644 --- a/documentations/Ergebnisse/Abschlussbericht_und_Praesentation/PhHo/4-4-2-database-generator.md +++ b/documentations/Ergebnisse/Abschlussbericht_und_Praesentation/PhHo/4-4-2-database-generator.md @@ -7,12 +7,56 @@ Auch wenn es seit einiger Zeit SQLAlchemy2 gibt haben wir uns entschieden mit Ve SQLAlchemy ist ein sehr mächtiges und beliebtes Werkzeug, leider ist die Projektdokumentation sehr undurchsichtig. Da aber SQLAlchemy1.4 zurzeit noch gewartet wird, ist dies für dieses Projekt kein Problem. -Hier ein kurzes Beipiel einer SQL-defintion via SQLAlchemy. - - -Dynamicly generated +Hier ein kurzes Beispiel einer SQL-Defintion via SQLAlchemy. ```python +import sqlalchemy as sa +from sqlalchemy.orm import declarative_base + + +Base = declarative_base() + +class DistrictCourt(Base): + """DistrictCourt.""" + + __tablename__ = "district_court" + id = sa.Column(sa.Integer, primary_key=True, autoincrement=True) + city = sa.Column(sa.String(100), nullable=False) + name = sa.Column(sa.String(100), nullable=False, unique=True) + + +class Company(Base): + """Company.""" + + __tablename__ = "company" + + __table_args__ = ( + sa.UniqueConstraint("hr", "court_id"), + sa.UniqueConstraint("name"), + ) + + id = sa.Column(sa.Integer, primary_key=True, autoincrement=True) + hr = sa.Column(sa.String, nullable=False) + court_id = sa.Column( + sa.Integer, + sa.ForeignKey("district_court.id"), + nullable=False, + ) + + name = sa.Column(sa.String(150), nullable=False) + founding_date = sa.Column(sa.Date, nullable=True) +``` + +Natürlich ist es manchmal sinnvoll SQL-Tabellen dynamischer und mit wenig Code-Duplication zu generieren. +Eine Möglichkeit dazu ist die folgende Definition in der die Union einiger Teildefinitionen als Dictionary. +So kann zum Beispiel eine Tabelle generiert werden, + in der ein Enumerationswert die Column angibt ohne das die Datenbank durch den Enum als Foreign Key aufgeblasen/verlangsamt wird. + +```python +from aki_prj23_transparenzregister.utils.enum_types import ( + FinancialKPIEnum, +) + AnnualFinanceStatement = type( "AnnualFinanceStatement", (Base,), @@ -26,129 +70,19 @@ AnnualFinanceStatement = type( ) ``` +Das Anlegen der Klassen alleine reicht nicht aus, um diese in einer SQL Datenbank anzulegen. +Diese müssen über das `Base`-Objekt wie folgt Initialisiert werden. + +```python +Base.metadata.create_all(db.bind) +``` + +Dabei ist `db` eine `sqlalchemy.orm.Session` welche über eine SQL-Engine mit einer Datenbank verbindet. + + +Das resultierende SQL-Schema sieht dan wie folgt aus: ```{eval-rst} .. drawio-figure:: test-db.drawio :format: png :page-index: 1 ``` - -```{mermaid} -classDiagram -direction BT -class annual_finance_statement { - integer company_id - date date - float revenue - float net_income - float ebit - float ebitda - float gross_profit - float operating_profit - float assets - float liabilities - float equity - float current_assets - float current_liabilities - float long_term_debt - float short_term_debt - float cash_and_cash_equivalents - float dividends - float cash_flow - integer id -} -class company { - varchar hr - integer court_id - varchar(150) name - varchar(26) company_type - date founding_date - varchar business_purpose - varchar(100) street - varchar(30) house_number - varchar(5) zip_code - varchar(100) city - float longitude - float latitude - float pos_accuracy - float capital_value - varchar(13) original_currency - varchar(12) capital_type - date last_update - varchar(100) sector - integer id -} -class district_court { - varchar(100) city - varchar(100) name - integer id -} -class news { - varchar(150) title - datetime timestamp - varchar text - varchar source_url - varchar source_domain - varchar(8) overall_sentiment_label - float overall_sentiment_certainty - integer number_of_companies - integer sum_of_times_named - integer id -} -class person { - varchar(100) firstname - varchar(100) lastname - date date_of_birth - varchar(100) works_for - varchar(100) street - varchar(10) house_number - varchar(5) zip_code - varchar(100) city - float longitude - float latitude - float pos_accuracy - integer id -} -class relation { - integer company_id - date date_from - date date_to - varchar(24) relation - integer id -} -class company_relation { - integer company2_id - integer id -} -class person_relation { - integer person_id - integer id -} -class sentiment { - integer company_id - integer article_id - integer times_named - varchar(8) specific_sentiment_label - float specific_sentiment_score - integer id -} - -class missing_company { - varchar(5) zip_code - varchar(100) city - integer number_of_links - boolean searched_for - varchar(150) name -} - - -annual_finance_statement --> company : company_id->id -company --> district_court : court_id->id -company_relation --> company : company2_id->id -company_relation --> relation : id -person_relation --> person : person_id -> id -person_relation --> relation : id -relation --> company : company_id -> id -sentiment --> company : company_id -> id -sentiment --> news : article_id -> id - -```