forked from datacontract/datacontract-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Support to Export to DBML (datacontract#215)
* Add Support to Export to DBML - Create basic project info from what the datacontract has - Map all the Models into tables, _not_ taking into regard nested fields (as there is no way to express them anyway) - Also create references, when they are given for a field, so the connections between tables become visible * Adapt CHANGELOG and README * Add generated info to make clear this is a generated file * Add support to convert to a specific servers data types - support selecting a server using --server - then the data types will be converted to the selected servers specific types
- Loading branch information
1 parent
26c9acf
commit 2908e2f
Showing
7 changed files
with
512 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
from datetime import datetime | ||
from importlib.metadata import version | ||
import pytz | ||
from datacontract.export.sql_type_converter import convert_to_sql_type | ||
import datacontract.model.data_contract_specification as spec | ||
from typing import Tuple | ||
|
||
|
||
def to_dbml_diagram(contract: spec.DataContractSpecification, server: spec.Server) -> str: | ||
|
||
result = '' | ||
result += add_generated_info(contract, server) + "\n" | ||
result += generate_project_info(contract) + "\n" | ||
|
||
for model_name, model in contract.models.items(): | ||
table_description = generate_table(model_name, model, server) | ||
result += f"\n{table_description}\n" | ||
|
||
return result | ||
|
||
def add_generated_info(contract: spec.DataContractSpecification, server: spec.Server) -> str: | ||
tz = pytz.timezone("UTC") | ||
now = datetime.now(tz) | ||
formatted_date = now.strftime("%b %d %Y") | ||
datacontract_cli_version = get_version() | ||
dialect = 'Logical Datacontract' if server is None else server.type | ||
|
||
generated_info = """ | ||
Generated at {0} by datacontract-cli version {1} | ||
for datacontract {2} ({3}) version {4} | ||
Using {5} Types for the field types | ||
""".format(formatted_date, datacontract_cli_version, contract.info.title, contract.id, contract.info.version, dialect) | ||
|
||
comment = """/* | ||
{0} | ||
*/ | ||
""".format(generated_info) | ||
|
||
note = """Note project_info {{ | ||
''' | ||
{0} | ||
''' | ||
}} | ||
""".format(generated_info) | ||
|
||
return """{0} | ||
{1} | ||
""".format(comment, note) | ||
|
||
def get_version() -> str: | ||
try: | ||
return version("datacontract_cli") | ||
except Exception: | ||
return "" | ||
|
||
def generate_project_info(contract: spec.DataContractSpecification) -> str: | ||
return """Project "{0}" {{ | ||
Note: "{1}" | ||
}}\n | ||
""".format(contract.info.title, ' '.join(contract.info.description.splitlines())) | ||
|
||
def generate_table(model_name: str, model: spec.Model, server: spec.Server) -> str: | ||
result = """Table "{0}" {{ | ||
Note: "{1}" | ||
""".format(model_name, ' '.join(model.description.splitlines())) | ||
|
||
references = [] | ||
|
||
# Add all the fields | ||
for field_name, field in model.fields.items(): | ||
ref, field_string = generate_field(field_name, field, model_name, server) | ||
if ref is not None: | ||
references.append(ref) | ||
result += "{0}\n".format(field_string) | ||
|
||
result += "}\n" | ||
|
||
# and if any: add the references | ||
if len(references) > 0: | ||
for ref in references: | ||
result += "Ref: {0}\n".format(ref) | ||
|
||
result += "\n" | ||
|
||
return result | ||
|
||
def generate_field(field_name: str, field: spec.Field, model_name: str, server: spec.Server) -> Tuple[str, str]: | ||
|
||
field_attrs = [] | ||
if field.primary: | ||
field_attrs.append('pk') | ||
|
||
if field.unique: | ||
field_attrs.append('unique') | ||
|
||
if field.required: | ||
field_attrs.append('not null') | ||
else: | ||
field_attrs.append('null') | ||
|
||
if field.description: | ||
field_attrs.append('Note: "{0}"'.format(' '.join(field.description.splitlines()))) | ||
|
||
field_type = field.type if server is None else convert_to_sql_type(field, server.type) | ||
|
||
field_str = '"{0}" "{1}" [{2}]'.format(field_name, field_type, ','.join(field_attrs)) | ||
ref_str = None | ||
if (field.references) is not None: | ||
# we always assume many to one, as datacontract doesn't really give us more info | ||
ref_str = "{0}.{1} > {2}".format(model_name, field_name, field.references) | ||
return (ref_str, field_str) |
Oops, something went wrong.