mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
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
77 lines
2.4 KiB
Python
Executable File
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"])
|