Skip to content

Commit

Permalink
Merge pull request #1437 from metemaddar/rewrite-database-functions
Browse files Browse the repository at this point in the history
[FEAT] init sql using command line args
  • Loading branch information
EPajares authored Aug 16, 2022
2 parents 1b5510a + 7186dda commit e3d6ae5
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 8 deletions.
52 changes: 49 additions & 3 deletions app/api/src/db/sql/init_sql.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#! /usr/bin/env python
import argparse
import sys
import textwrap
from pathlib import Path

from alembic_utils.pg_function import PGFunction
Expand All @@ -7,7 +11,7 @@

from src.core.config import settings
from src.db.session import legacy_engine
from src.db.sql.utils import sorted_path_by_dependency
from src.db.sql.utils import report, sorted_path_by_dependency


def sql_function_entities():
Expand Down Expand Up @@ -71,6 +75,48 @@ def upgrade_triggers():
legacy_engine.execute(text(statement.text))


def run(args):
action = args.action
material = args.material
if action == "report":
report()
else:
globals()[f"{action}_{material}"]()
print(f"{action.title()} {material} complete!")


def main():
parser = argparse.ArgumentParser(
description="Upgrade and Downgrade sql functions and triggers",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=textwrap.dedent(
"""
example usage:
cd /app
python src/db/sql/init_sql.py upgrade -m functions
python src/db/sql/init_sql.py downgrade -m triggers
python src/db/sql/init_sql.py report
"""
),
)
parser.add_argument(
"action",
help="The action to do on database",
choices=["upgrade", "downgrade", "report"],
type=str,
)
parser.add_argument(
"--material",
"-m",
required="upgrade" in sys.argv or "downgrade" in sys.argv,
help="functions or triggers",
choices=["functions", "triggers"],
type=str,
)
parser.set_defaults(func=run)
args = parser.parse_args()
args.func(args)


if __name__ == "__main__":
upgrade_functions()
print()
main()
71 changes: 66 additions & 5 deletions app/api/src/db/sql/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import functools
import os
from collections import namedtuple
from collections import defaultdict, namedtuple
from pathlib import Path

import rich
from sqlalchemy import text

from src.core.config import settings
from src.db.session import legacy_engine


def find_unapplied_dependencies(function_content, function_list):
dependencies = set()
Expand Down Expand Up @@ -51,7 +58,61 @@ def sorted_path_by_dependency(path_list):
return new_path_list


if __name__ == "__main__":
path_list = Path(str(Path().resolve()) + "/src/db/sql/functions").rglob("*.sql")
new_path_list = sorted_path_by_dependency(path_list)
print(new_path_list)
def list_functions():
query = """
SELECT
routine_name
FROM
information_schema.routines
WHERE
routine_type = 'FUNCTION'
AND
routine_schema = :functions_schema;
"""
query = text(query)
with legacy_engine.connect() as session:
functions = session.execute(
query, {"functions_schema": settings.POSTGRES_FUNCTIONS_SCHEMA}
)
return [f["routine_name"] for f in functions]


def report():
function_paths = Path(str(Path().resolve()) + "/src/db/sql/functions").rglob("*.sql")
triger_paths = Path(str(Path().resolve()) + "/src/db/sql/triggers").glob("*.sql")
files = list(function_paths) + list(triger_paths)

functions = list_functions()
classified_functions = defaultdict(list)
not_in_db = []
for fn in files:
if not fn:
continue

file_name = fn.parts[-1]
directory_name = fn.parts[-2]
if get_name_from_path(fn) in functions:
functions.remove(get_name_from_path(fn))
else:
not_in_db.append((directory_name, file_name))
classified_functions[directory_name].append(file_name)

for key in classified_functions.keys():
rich.print(f"[bold blue]## {key}/[/bold blue]")
for fn in classified_functions[key]:
print("- ", fn)
print()
if functools:
rich.print(f"[bold red]# in db but not in files:[/bold red]")
for fn in functions:
rich.print(f"[orange1]- {fn}[/orange1]")
else:
rich.print(f"[bold green]All database function names found in files.[/bold green]")

print()
if not_in_db:
rich.print(f"[bold red]## in files but not in db:[/bold red]")
for fn in not_in_db:
rich.print(f"- {fn[0]}/[orange1]{fn[1]}[/orange1]")
else:
rich.print(f"[bold green]All function file names found in database.[/bold green]")

0 comments on commit e3d6ae5

Please sign in to comment.