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
9namespace DB
10{
11namespace
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
123String ASTCreateRowPolicyQuery::getID(char) const
124{
125 return "CREATE POLICY or ALTER POLICY query";
126}
127
128
129ASTPtr ASTCreateRowPolicyQuery::clone() const
130{
131 return std::make_shared<ASTCreateRowPolicyQuery>(*this);
132}
133
134
135void 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