Files
codeql/swift/codegen/dbschemegen.py
Paolo Tranquilli 91fd83a554 Swift: dbscheme generator
This patch introduces the basic infrastructure of the code generation
suite and the `dbscheme` generator.

Notice that the checked in `schema.yml` should reflect swift 5.6 but
might need some tweaking.

Closes https://github.com/github/codeql-c-team/issues/979
2022-04-14 11:27:41 +02:00

77 lines
2.4 KiB
Python
Executable File

#!/usr/bin/env python3
import inflection
from lib.renderer import Renderer
from lib.dbscheme import *
from lib import paths, schema, generator
log = logging.getLogger(__name__)
def dbtype(typename):
if typename[0].isupper():
return "@" + inflection.underscore(typename)
return typename
def cls_to_dbscheme(cls: schema.Class):
if cls.derived:
yield DbUnion(dbtype(cls.name), (dbtype(c) for c in cls.derived))
if not cls.derived or any(f.is_single() for f in cls.fields):
binding = not cls.derived
keyset = DbKeySet(["id"]) if cls.derived else None
yield DbTable(
keyset=keyset,
name=inflection.tableize(cls.name),
columns=[
DbColumn("id", type=dbtype(cls.name), binding=binding),
] + [
DbColumn(f.name, dbtype(f.type)) for f in cls.fields if f.is_single()
]
)
for f in cls.fields:
if f.is_optional():
yield DbTable(
keyset=DbKeySet(["id"]),
name=inflection.tableize(f"{cls.name}_{f.name}"),
columns=[
DbColumn("id", type=dbtype(cls.name)),
DbColumn(f.name, dbtype(f.type)),
],
)
elif f.is_repeated():
yield DbTable(
keyset=DbKeySet(["id", "index"]),
name=inflection.tableize(f"{cls.name}_{f.name}"),
columns=[
DbColumn("id", type=dbtype(cls.name)),
DbColumn("index", type="int"),
DbColumn(inflection.singularize(f.name), dbtype(f.type)),
]
)
def generate(opts):
input = opts.schema.resolve()
out = opts.dbscheme.resolve()
renderer = Renderer(opts.check)
with open(input) as src:
data = schema.load(src)
declarations = [d for cls in data.classes.values() for d in cls_to_dbscheme(cls)]
includes = []
for inc in data.includes:
inc = input.parent / inc
with open(inc) as inclusion:
includes.append({"src": inc.relative_to(paths.swift_dir), "data": inclusion.read()})
renderer.render("dbscheme", out, includes=includes, src=input.relative_to(paths.swift_dir),
declarations=declarations)
return renderer.written
if __name__ == "__main__":
generator.run(generate, tags=["schema", "dbscheme"])