bool filterBlockWithQuery(ASTPtr query, Block & block, const Context & context) { query = query->clone(); const ASTSelectQuery & select = typeid_cast<ASTSelectQuery & >(*query); if (!select.where_expression && !select.prewhere_expression) return false; NameSet columns; for (const auto & it : block.getColumnsList()) columns.insert(it.name); /// Составим выражение, вычисляющее выражения в WHERE и PREWHERE, зависящие только от имеющихся столбцов. std::vector<ASTPtr> functions; if (select.where_expression) extractFunctions(select.where_expression, columns, functions); if (select.prewhere_expression) extractFunctions(select.prewhere_expression, columns, functions); ASTPtr expression_ast = buildWhereExpression(functions); if (!expression_ast) return false; /// Распарсим и вычислим выражение. ExpressionAnalyzer analyzer(expression_ast, context, {}, block.getColumnsList()); ExpressionActionsPtr actions = analyzer.getActions(false); actions->execute(block); /// Отфильтруем блок. String filter_column_name = expression_ast->getColumnName(); ColumnPtr filter_column = block.getByName(filter_column_name).column; if (auto converted = filter_column->convertToFullColumnIfConst()) filter_column = converted; const IColumn::Filter & filter = dynamic_cast<ColumnUInt8 &>(*filter_column).getData(); if (std::accumulate(filter.begin(), filter.end(), 0ul) == filter.size()) return false; for (size_t i = 0; i < block.columns(); ++i) { ColumnPtr & column = block.safeGetByPosition(i).column; column = column->filter(filter, -1); } return true; }
bool filterBlockWithQuery(const ASTPtr & query, Block & block, const Context & context) { const ASTSelectQuery & select = typeid_cast<const ASTSelectQuery & >(*query); if (!select.where_expression && !select.prewhere_expression) return false; NameSet columns; for (const auto & it : block.getColumnsList()) columns.insert(it.name); /// We will create an expression that evaluates the expressions in WHERE and PREWHERE, depending only on the existing columns. std::vector<ASTPtr> functions; if (select.where_expression) extractFunctions(select.where_expression, columns, functions); if (select.prewhere_expression) extractFunctions(select.prewhere_expression, columns, functions); ASTPtr expression_ast = buildWhereExpression(functions); if (!expression_ast) return false; /// Let's parse and calculate the expression. ExpressionAnalyzer analyzer(expression_ast, context, {}, block.getColumnsList()); ExpressionActionsPtr actions = analyzer.getActions(false); actions->execute(block); /// Filter the block. String filter_column_name = expression_ast->getColumnName(); ColumnPtr filter_column = block.getByName(filter_column_name).column; if (auto converted = filter_column->convertToFullColumnIfConst()) filter_column = converted; const IColumn::Filter & filter = dynamic_cast<ColumnUInt8 &>(*filter_column).getData(); if (countBytesInFilter(filter) == 0) return false; for (size_t i = 0; i < block.columns(); ++i) { ColumnPtr & column = block.safeGetByPosition(i).column; column = column->filter(filter, -1); } return true; }
/// Extract all subfunctions of the main conjunction, but depending only on the specified columns static void extractFunctions(ASTPtr expression, const NameSet & columns, std::vector<ASTPtr> & result) { const ASTFunction * function = typeid_cast<const ASTFunction *>(&*expression); if (function && function->name == "and") { for (size_t i = 0; i < function->arguments->children.size(); ++i) extractFunctions(function->arguments->children[i], columns, result); } else if (isValidFunction(expression, columns)) { result.push_back(expression->clone()); } }