summaryrefslogtreecommitdiffstats
path: root/yql/essentials/sql/v1/ide/completion/name/object/simple/static/schema_json.cpp
blob: dba0330ea8cb7b801fe04eef907132758deb475a (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
#include "schema_json.h"

#include "schema.h"

#include <util/generic/hash.h>
#include <util/generic/vector.h>
#include <util/generic/scope.h>
#include <util/string/join.h>

namespace NSQLComplete {

namespace {

TString PathString(const TVector<TString>& path) {
    return "/" + JoinSeq("/", path);
}

const NJson::TJsonValue& Expect(
    const TVector<TString>& path,
    const NJson::TJsonValue::TMapType& json,
    TStringBuf key) {
    if (!json.contains(key)) {
        ythrow yexception() << "At " << PathString(path) << " expected " << key;
    }
    return json.at(key);
}

const NJson::TJsonValue::TMapType& ExpectMap(
    const TVector<TString>& path,
    const NJson::TJsonValue& json) {
    if (!json.IsMap()) {
        ythrow yexception() << "At " << PathString(path) << " expected Map";
    }
    return json.GetMapSafe();
}

const NJson::TJsonValue::TMapType& ExpectMap(
    const TVector<TString>& path,
    const NJson::TJsonValue::TMapType& json,
    TStringBuf key) {
    Expect(path, json, key);
    return ExpectMap(path, json.at(key));
}

TString Parse(
    const TString& cluster,
    const NJson::TJsonValue::TMapType& json,
    TSchemaData& data,
    TVector<TString>& path);

void ParseFolder(
    const TString& cluster,
    const NJson::TJsonValue::TMapType& json,
    TSchemaData& data,
    TVector<TString>& path) {
    for (const auto& [name, entry] : ExpectMap(path, json, "entries")) {
        path.emplace_back(name);
        TString type = Parse(cluster, ExpectMap(path, entry), data, path);
        path.pop_back();

        TStringBuf suffix = (!path.empty()) ? "/" : "";
        data.Folders[cluster][PathString(path) + suffix].emplace_back(type, name);
    }
}

void ParseTable(
    const TString& cluster,
    const NJson::TJsonValue::TMapType& json,
    TSchemaData& data,
    TVector<TString>& path) {
    for (const auto& [name, _] : ExpectMap(path, json, "columns")) {
        data.Tables[cluster][PathString(path)].Columns.emplace_back(name);
    }
}

TString Parse(
    const TString& cluster,
    const NJson::TJsonValue::TMapType& json,
    TSchemaData& data,
    TVector<TString>& path) {
    auto type = Expect(path, json, "type");

    if (type == TFolderEntry::Folder) {
        ParseFolder(cluster, json, data, path);
        return TFolderEntry::Folder;
    }

    if (type == TFolderEntry::Table) {
        ParseTable(cluster, json, data, path);
        return TFolderEntry::Table;
    }

    if (!type.IsString()) {
        ythrow yexception() << "Unexpected type: " << type;
    }

    return type.GetStringSafe();
}

} // namespace

ISimpleSchema::TPtr MakeStaticSimpleSchema(const NJson::TJsonMap& json) {
    TSchemaData data;

    for (const auto& [cluster, tree] : json.GetMap()) {
        TVector<TString> path;
        ParseFolder(cluster, tree.GetMapSafe(), data, path);
    }

    return MakeStaticSimpleSchema(std::move(data));
}

} // namespace NSQLComplete