aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/sqlitestudiocli/commands/clicommandtree.cpp
blob: c99fe665ed883ad3ed598e09787743d86be5f3b3 (plain) (blame)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "clicommandtree.h"
#include "cli.h"
#include "common/sortedhash.h"
#include "common/unused.h"

const QString CliCommandTree::metaNodeNameTemplate = "<%1>";

void CliCommandTree::execute()
{
    if (!cli->getCurrentDb())
    {
        println(tr("No current working database is selected. Use %1 to define one and then run %2.").arg(cmdName("use")).arg(cmdName("tree")));
        return;
    }

    bool printColumns = syntax.isOptionSet(COLUMNS);
    bool printSystemObjects = syntax.isOptionSet(SYSTEM_OBJECTS);

    SchemaResolver resolver(cli->getCurrentDb());
    resolver.setIgnoreSystemObjects(!printSystemObjects);

    QStringList databases;
    if (syntax.isArgumentSet(INTRNAL_DB))
    {
        databases << syntax.getArgument(INTRNAL_DB);
    }
    else
    {
        databases << "main" << "temp";
        databases += resolver.getDatabases().toList();
    }

    AsciiTree tree;
    tree.label = cli->getCurrentDb()->getName();
    for (const QString& database : databases)
    {
        tree.childs << getDatabaseTree(database, resolver, printColumns);
    }

    println();
    println(toAsciiTree(tree));
    println();
}

AsciiTree CliCommandTree::getDatabaseTree(const QString& database, SchemaResolver& resolver, bool printColumns)
{
    QStringList tables = resolver.getTables(database);
    QStringList views = resolver.getViews(database);

    AsciiTree tree;
    AsciiTree tablesTree;
    AsciiTree viewsTree;

    tablesTree.label = metaNodeNameTemplate.arg(tr("Tables"));
    for (const QString& table : tables)
        tablesTree.childs << getTableTree(database, table, resolver, printColumns);

    viewsTree.label = metaNodeNameTemplate.arg(tr("Views"));
    for (const QString& view : views)
        viewsTree.childs << getViewTree(database, view, resolver);

    tree.label = database;
    tree.childs << tablesTree << viewsTree;
    return tree;
}

AsciiTree CliCommandTree::getTableTree(const QString& database, const QString& table, SchemaResolver& resolver, bool printColumns)
{
    QStringList columns;
    if (printColumns)
        columns = resolver.getTableColumns(database, table);

    QStringList indexes = resolver.getIndexesForTable(database, table);
    QStringList triggers = resolver.getTriggersForTable(database, table);

    AsciiTree tree;
    AsciiTree columnsTree;
    AsciiTree indexesTree;
    AsciiTree triggersTree;

    if (printColumns)
    {
        columnsTree.label = metaNodeNameTemplate.arg(tr("Columns"));
        for (const QString& column : columns)
            columnsTree.childs << getTreeLeaf(column);
    }

    indexesTree.label = metaNodeNameTemplate.arg(tr("Indexes"));
    for (const QString& index : indexes)
        indexesTree.childs << getTreeLeaf(index);

    triggersTree.label = metaNodeNameTemplate.arg(tr("Triggers"));
    for (const QString& trig : triggers)
        triggersTree.childs << getTreeLeaf(trig);

    if (printColumns)
        tree.childs << columnsTree;

    tree.label = table;
    tree.childs << indexesTree;
    tree.childs << triggersTree;

    return tree;
}

AsciiTree CliCommandTree::getViewTree(const QString& database, const QString& view, SchemaResolver& resolver)
{
    QStringList triggers = resolver.getTriggersForView(database, view);

    AsciiTree tree;
    AsciiTree triggersTree;

    triggersTree.label = metaNodeNameTemplate.arg(tr("Triggers"));
    for (const QString& trig : triggers)
        triggersTree.childs << getTreeLeaf(trig);

    tree.label = view;
    tree.childs << triggersTree;

    return tree;
}

AsciiTree CliCommandTree::getTreeLeaf(const QString& column)
{
    AsciiTree tree;
    tree.label = column;
    return tree;
}

QString CliCommandTree::shortHelp() const
{
    return tr("prints all objects in the database as a tree");
}

QString CliCommandTree::fullHelp() const
{
    return tr(
                "Prints all objects (tables, indexes, triggers and views) that are in the database as a tree. "
                "The tree is very similar to the one that you can see in GUI client of the SQLiteStudio.\n"
                "When -c option is given, then also columns will be listed under each table.\n"
                "When -s option is given, then also system objects will be printed (sqlite_* tables, autoincrement indexes, etc).\n"
                "The database argument is optional and if provided, then only given database will be printed. This is not a registered database name, "
                "but instead it's an internal SQLite database name, like 'main', 'temp', or any attached database name. To print tree for other "
                "registered database, call %1 first to switch the working database, and then use %2 command."
             ).arg(cmdName("use")).arg(cmdName("tree"));
}

void CliCommandTree::defineSyntax()
{
    syntax.setName("tree");
    syntax.addOptionShort(COLUMNS, "c");
    syntax.addOptionShort(SYSTEM_OBJECTS, "s");
    syntax.addArgument(INTRNAL_DB, "database", false);
}