| 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 | |