summaryrefslogtreecommitdiff
path: root/tools/schema_generator.py
blob: c84e24b73e578c3bb229f51798f4565d0ccc02aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/usr/bin/env python

#    Copyright (C) 2014 Yahoo! Inc. All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import contextlib
import re

import tabulate

from taskflow.persistence.backends import impl_sqlalchemy

NAME_MAPPING = {
    'flowdetails': 'Flow details',
    'atomdetails': 'Atom details',
    'logbooks': 'Logbooks',
}
CONN_CONF = {
    # This uses an in-memory database (aka nothing is written)
    "connection": "sqlite://",
}
TABLE_QUERY = "SELECT name, sql FROM sqlite_master WHERE type='table'"
SCHEMA_QUERY = "pragma table_info(%s)"


def to_bool_string(val):
    if isinstance(val, (int, bool)):
        return str(bool(val))
    if not isinstance(val, str):
        val = str(val)
    if val.lower() in ('0', 'false'):
        return 'False'
    if val.lower() in ('1', 'true'):
        return 'True'
    raise ValueError("Unknown boolean input '%s'" % (val))


def main():
    backend = impl_sqlalchemy.SQLAlchemyBackend(CONN_CONF)
    with contextlib.closing(backend) as backend:
        # Make the schema exist...
        with contextlib.closing(backend.get_connection()) as conn:
            conn.upgrade()
        # Now make a prettier version of that schema...
        tables = backend.engine.execute(TABLE_QUERY)
        table_names = [r[0] for r in tables]
        for i, table_name in enumerate(table_names):
            pretty_name = NAME_MAPPING.get(table_name, table_name)
            print("*" + pretty_name + "*")
            # http://www.sqlite.org/faq.html#q24
            table_name = table_name.replace("\"", "\"\"")
            rows = []
            for r in backend.engine.execute(SCHEMA_QUERY % table_name):
                # Cut out the numbers from things like VARCHAR(12) since
                # this is not very useful to show users who just want to
                # see the basic schema...
                row_type = re.sub(r"\(.*?\)", "", r['type']).strip()
                if not row_type:
                    raise ValueError("Row %s of table '%s' was empty after"
                                     " cleaning" % (r['cid'], table_name))
                rows.append([r['name'], row_type, to_bool_string(r['pk'])])
            contents = tabulate.tabulate(
                rows, headers=['Name', 'Type', 'Primary Key'],
                tablefmt="rst")
            print("\n%s" % contents.strip())
            if i + 1 != len(table_names):
                print("")


if __name__ == '__main__':
    main()