1 | #include <Parsers/ASTCreateRowPolicyQuery.h> |
2 | #include <Parsers/ASTRoleList.h> |
3 | #include <Parsers/formatAST.h> |
4 | #include <Common/quoteString.h> |
5 | #include <boost/range/algorithm/transform.hpp> |
6 | #include <sstream> |
7 | |
8 | |
9 | namespace DB |
10 | { |
11 | namespace |
12 | { |
13 | using ConditionIndex = RowPolicy::ConditionIndex; |
14 | |
15 | void formatRenameTo(const String & new_policy_name, const IAST::FormatSettings & settings) |
16 | { |
17 | settings.ostr << (settings.hilite ? IAST::hilite_keyword : "" ) << " RENAME TO " << (settings.hilite ? IAST::hilite_none : "" ) |
18 | << backQuote(new_policy_name); |
19 | } |
20 | |
21 | |
22 | void formatIsRestrictive(bool is_restrictive, const IAST::FormatSettings & settings) |
23 | { |
24 | settings.ostr << (settings.hilite ? IAST::hilite_keyword : "" ) << " AS " << (is_restrictive ? "RESTRICTIVE" : "PERMISSIVE" ) |
25 | << (settings.hilite ? IAST::hilite_none : "" ); |
26 | } |
27 | |
28 | |
29 | void formatConditionalExpression(const ASTPtr & expr, const IAST::FormatSettings & settings) |
30 | { |
31 | if (!expr) |
32 | { |
33 | settings.ostr << (settings.hilite ? IAST::hilite_keyword : "" ) << " NONE" << (settings.hilite ? IAST::hilite_none : "" ); |
34 | return; |
35 | } |
36 | expr->format(settings); |
37 | } |
38 | |
39 | |
40 | std::vector<std::pair<ConditionIndex, String>> |
41 | conditionalExpressionsToStrings(const std::vector<std::pair<ConditionIndex, ASTPtr>> & exprs, const IAST::FormatSettings & settings) |
42 | { |
43 | std::vector<std::pair<ConditionIndex, String>> result; |
44 | std::stringstream ss; |
45 | IAST::FormatSettings temp_settings(ss, settings); |
46 | boost::range::transform(exprs, std::back_inserter(result), [&](const std::pair<ConditionIndex, ASTPtr> & in) |
47 | { |
48 | formatConditionalExpression(in.second, temp_settings); |
49 | auto out = std::pair{in.first, ss.str()}; |
50 | ss.str("" ); |
51 | return out; |
52 | }); |
53 | return result; |
54 | } |
55 | |
56 | |
57 | void formatConditions(const char * op, const std::optional<String> & filter, const std::optional<String> & check, bool alter, const IAST::FormatSettings & settings) |
58 | { |
59 | if (op) |
60 | { |
61 | settings.ostr << (settings.hilite ? IAST::hilite_keyword : "" ) << " FOR" << (settings.hilite ? IAST::hilite_none : "" ); |
62 | settings.ostr << (settings.hilite ? IAST::hilite_keyword : "" ) << ' ' << op << (settings.hilite ? IAST::hilite_none : "" ); |
63 | } |
64 | |
65 | if (filter) |
66 | settings.ostr << (settings.hilite ? IAST::hilite_keyword : "" ) << " USING " << (settings.hilite ? IAST::hilite_none : "" ) << *filter; |
67 | |
68 | if (check && (alter || (check != filter))) |
69 | settings.ostr << (settings.hilite ? IAST::hilite_keyword : "" ) << " WITH CHECK " << (settings.hilite ? IAST::hilite_none : "" ) << *check; |
70 | } |
71 | |
72 | |
73 | void formatMultipleConditions(const std::vector<std::pair<ConditionIndex, ASTPtr>> & conditions, bool alter, const IAST::FormatSettings & settings) |
74 | { |
75 | std::optional<String> scond[RowPolicy::MAX_CONDITION_INDEX]; |
76 | for (const auto & [index, scondition] : conditionalExpressionsToStrings(conditions, settings)) |
77 | scond[index] = scondition; |
78 | |
79 | if ((scond[RowPolicy::SELECT_FILTER] == scond[RowPolicy::UPDATE_FILTER]) |
80 | && (scond[RowPolicy::UPDATE_FILTER] == scond[RowPolicy::DELETE_FILTER]) |
81 | && (scond[RowPolicy::INSERT_CHECK] == scond[RowPolicy::UPDATE_CHECK]) |
82 | && (scond[RowPolicy::SELECT_FILTER] || scond[RowPolicy::INSERT_CHECK])) |
83 | { |
84 | formatConditions(nullptr, scond[RowPolicy::SELECT_FILTER], scond[RowPolicy::INSERT_CHECK], alter, settings); |
85 | return; |
86 | } |
87 | |
88 | bool need_comma = false; |
89 | if (scond[RowPolicy::SELECT_FILTER]) |
90 | { |
91 | if (std::exchange(need_comma, true)) |
92 | settings.ostr << ','; |
93 | formatConditions("SELECT" , scond[RowPolicy::SELECT_FILTER], {}, alter, settings); |
94 | } |
95 | if (scond[RowPolicy::INSERT_CHECK]) |
96 | { |
97 | if (std::exchange(need_comma, true)) |
98 | settings.ostr << ','; |
99 | formatConditions("INSERT" , {}, scond[RowPolicy::INSERT_CHECK], alter, settings); |
100 | } |
101 | if (scond[RowPolicy::UPDATE_FILTER] || scond[RowPolicy::UPDATE_CHECK]) |
102 | { |
103 | if (std::exchange(need_comma, true)) |
104 | settings.ostr << ','; |
105 | formatConditions("UPDATE" , scond[RowPolicy::UPDATE_FILTER], scond[RowPolicy::UPDATE_CHECK], alter, settings); |
106 | } |
107 | if (scond[RowPolicy::DELETE_FILTER]) |
108 | { |
109 | if (std::exchange(need_comma, true)) |
110 | settings.ostr << ','; |
111 | formatConditions("DELETE" , scond[RowPolicy::DELETE_FILTER], {}, alter, settings); |
112 | } |
113 | } |
114 | |
115 | void formatRoles(const ASTRoleList & roles, const IAST::FormatSettings & settings) |
116 | { |
117 | settings.ostr << (settings.hilite ? IAST::hilite_keyword : "" ) << " TO " << (settings.hilite ? IAST::hilite_none : "" ); |
118 | roles.format(settings); |
119 | } |
120 | } |
121 | |
122 | |
123 | String ASTCreateRowPolicyQuery::getID(char) const |
124 | { |
125 | return "CREATE POLICY or ALTER POLICY query" ; |
126 | } |
127 | |
128 | |
129 | ASTPtr ASTCreateRowPolicyQuery::clone() const |
130 | { |
131 | return std::make_shared<ASTCreateRowPolicyQuery>(*this); |
132 | } |
133 | |
134 | |
135 | void ASTCreateRowPolicyQuery::formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const |
136 | { |
137 | settings.ostr << (settings.hilite ? hilite_keyword : "" ) << (alter ? "ALTER POLICY" : "CREATE POLICY" ) |
138 | << (settings.hilite ? hilite_none : "" ); |
139 | |
140 | if (if_exists) |
141 | settings.ostr << (settings.hilite ? hilite_keyword : "" ) << " IF EXISTS" << (settings.hilite ? hilite_none : "" ); |
142 | else if (if_not_exists) |
143 | settings.ostr << (settings.hilite ? hilite_keyword : "" ) << " IF NOT EXISTS" << (settings.hilite ? hilite_none : "" ); |
144 | else if (or_replace) |
145 | settings.ostr << (settings.hilite ? hilite_keyword : "" ) << " OR REPLACE" << (settings.hilite ? hilite_none : "" ); |
146 | |
147 | const String & database = name_parts.database; |
148 | const String & table_name = name_parts.table_name; |
149 | const String & policy_name = name_parts.policy_name; |
150 | settings.ostr << " " << backQuoteIfNeed(policy_name) << (settings.hilite ? hilite_keyword : "" ) << " ON " |
151 | << (settings.hilite ? hilite_none : "" ) << (database.empty() ? String{} : backQuoteIfNeed(database) + "." ) << table_name; |
152 | |
153 | if (!new_policy_name.empty()) |
154 | formatRenameTo(new_policy_name, settings); |
155 | |
156 | if (is_restrictive) |
157 | formatIsRestrictive(*is_restrictive, settings); |
158 | |
159 | formatMultipleConditions(conditions, alter, settings); |
160 | |
161 | if (roles) |
162 | formatRoles(*roles, settings); |
163 | } |
164 | } |
165 | |