bedrock.generators.generate-db-schema
This script generates the SQL schema for the database.
It works by introspecting the models in the model/ directory and generating the SQL schema for them.
It relies on SQLAlchemy's CreateTable function to generate the SQL schema.
1""" 2This script generates the SQL schema for the database. 3 4It works by introspecting the models in the `model/` directory and generating the SQL schema for them. 5 6It relies on SQLAlchemy's `CreateTable` function to generate the SQL schema. 7""" 8import re 9import sys 10from enum import Enum 11 12from sqlalchemy.dialects import postgresql 13from sqlalchemy.schema import CreateTable, CreateIndex 14from bedrock.config.models import get_models 15 16 17def shorten_table_name(name: str) -> str: 18 """ 19 Shorten a table name to an acronym. 20 :param name: The name of the table 21 """ 22 return "".join([w[0] for w in f"{name}".split("_")]) 23 24 25if __name__ == "__main__": 26 BASE_PATH = sys.argv[1] 27 sys.path.insert(0, f"{BASE_PATH}") 28 models = get_models( 29 f"{BASE_PATH}/model" if len(sys.argv) > 1 else "../model", 30 sys.argv[2] if len(sys.argv) > 2 else "model." 31 ) 32 33 enum_statements = set() 34 for model in models: 35 for column in model.__table__.columns: 36 if issubclass(column.type.python_type, Enum) and column.type.enums: 37 values = ', '.join([f'\'{e}\'' for e in column.type.enums]) 38 enum_statements.add(f"CREATE TYPE {column.type.name} AS ENUM ({values});") 39 40 create_statements = [] 41 foreign_keys = [] 42 indexes = [] 43 reserved_words = ["name", "label", "message", "data", "sequence"] 44 45 comma_parenthesis_regex = re.compile(r",\s*(\n\s*)*\)") 46 referenced_table_regex = re.compile(r"REFERENCES (.*) \(") 47 for model in models: 48 create_statement = f"{CreateTable(model.__table__).compile(dialect=postgresql.dialect())}".replace("\n\n", "\n") 49 for word in reserved_words: 50 create_statement = re.sub(fr"(\s)({word}) (VARCHAR|INTEGER|JSONB)", r"""\1"\2" \3""", create_statement) 51 # Do Foreign Keys 52 matches = re.findall(r"(FOREIGN KEY.*)", create_statement) 53 if matches: 54 for m in matches: 55 referenced_table = referenced_table_regex.findall(m)[0] 56 fk_name = f"fk_{shorten_table_name(model.__table__)}_{shorten_table_name(referenced_table)}" 57 fk_statement = f"ALTER TABLE {model.__table__} ADD CONSTRAINT {fk_name} {m};".replace(", ;", ";") 58 foreign_keys.append(fk_statement) 59 create_statement = comma_parenthesis_regex.sub("\n)", create_statement.replace(m, "")) 60 create_statements.append(f"{create_statement};".replace("\n;", ";")) 61 # Do Indexes 62 indexes.extend(f"{CreateIndex(idx).compile(dialect=postgresql.dialect())};" for idx in model.__table__.indexes) 63 64 print("\n".join(enum_statements)) 65 print("\n") 66 print("\n".join(create_statements)) 67 print("\n") 68 print("\n".join(foreign_keys)) 69 print("\n") 70 print("\n".join(indexes)) 71 print("\n")
def
shorten_table_name(name: str) -> str:
18def shorten_table_name(name: str) -> str: 19 """ 20 Shorten a table name to an acronym. 21 :param name: The name of the table 22 """ 23 return "".join([w[0] for w in f"{name}".split("_")])
Shorten a table name to an acronym.
Parameters
- name: The name of the table