Assumes `storage` is set and the table filter (row-level security) is not empty.
| 244 | |
| 245 | /// Assumes `storage` is set and the table filter (row-level security) is not empty. |
| 246 | static FilterDAGInfoPtr generateFilterActions( |
| 247 | const StorageID & table_id, |
| 248 | const ASTPtr & row_policy_filter_expression, |
| 249 | const ContextPtr & context, |
| 250 | const StoragePtr & storage, |
| 251 | const StorageSnapshotPtr & storage_snapshot, |
| 252 | const StorageMetadataPtr & metadata_snapshot, |
| 253 | Names & prerequisite_columns, |
| 254 | PreparedSetsPtr prepared_sets) |
| 255 | try |
| 256 | { |
| 257 | auto filter_info = std::make_shared<FilterDAGInfo>(); |
| 258 | |
| 259 | const auto & db_name = table_id.getDatabaseName(); |
| 260 | const auto & table_name = table_id.getTableName(); |
| 261 | |
| 262 | /// TODO: implement some AST builders for this kind of stuff |
| 263 | ASTPtr query_ast = make_intrusive<ASTSelectQuery>(); |
| 264 | auto * select_ast = query_ast->as<ASTSelectQuery>(); |
| 265 | |
| 266 | select_ast->setExpression(ASTSelectQuery::Expression::SELECT, make_intrusive<ASTExpressionList>()); |
| 267 | auto expr_list = select_ast->select(); |
| 268 | |
| 269 | /// The first column is our filter expression. |
| 270 | /// the row_policy_filter_expression should be cloned, because it may be changed by TreeRewriter. |
| 271 | /// which make it possible an invalid expression, although it may be valid in whole select. |
| 272 | expr_list->children.push_back(row_policy_filter_expression->clone()); |
| 273 | |
| 274 | /// Keep columns that are required after the filter actions. |
| 275 | for (const auto & column_str : prerequisite_columns) |
| 276 | { |
| 277 | ParserExpression expr_parser; |
| 278 | /// We should add back quotes around column name as it can contain dots. |
| 279 | expr_list->children.push_back(parseQuery( |
| 280 | expr_parser, |
| 281 | backQuoteIfNeed(column_str), |
| 282 | 0, |
| 283 | context->getSettingsRef()[Setting::max_parser_depth], |
| 284 | context->getSettingsRef()[Setting::max_parser_backtracks])); |
| 285 | } |
| 286 | |
| 287 | select_ast->setExpression(ASTSelectQuery::Expression::TABLES, make_intrusive<ASTTablesInSelectQuery>()); |
| 288 | auto tables = select_ast->tables(); |
| 289 | auto tables_elem = make_intrusive<ASTTablesInSelectQueryElement>(); |
| 290 | auto table_expr = make_intrusive<ASTTableExpression>(); |
| 291 | tables->children.push_back(tables_elem); |
| 292 | tables_elem->table_expression = table_expr; |
| 293 | tables_elem->children.push_back(table_expr); |
| 294 | table_expr->database_and_table_name = make_intrusive<ASTTableIdentifier>(db_name, table_name); |
| 295 | table_expr->children.push_back(table_expr->database_and_table_name); |
| 296 | |
| 297 | /// Using separate expression analyzer to prevent any possible alias injection |
| 298 | auto syntax_result = TreeRewriter(context).analyzeSelect(query_ast, TreeRewriterResult({}, storage, storage_snapshot)); |
| 299 | SelectQueryExpressionAnalyzer analyzer(query_ast, syntax_result, context, metadata_snapshot, {}, false, {}, prepared_sets); |
| 300 | filter_info->actions = std::move(analyzer.simpleSelectActions()->dag); |
| 301 | |
| 302 | filter_info->column_name = expr_list->children.at(0)->getColumnName(); |
| 303 | filter_info->actions.removeUnusedActions(NameSet{filter_info->column_name}); |
no test coverage detected