diff --git a/src/Interpreters/InterpreterInsertQuery.cpp b/src/Interpreters/InterpreterInsertQuery.cpp index 9d33650405a..01fee30a445 100644 --- a/src/Interpreters/InterpreterInsertQuery.cpp +++ b/src/Interpreters/InterpreterInsertQuery.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,8 @@ #include #include #include +#include +#include namespace { @@ -90,9 +93,30 @@ Block InterpreterInsertQuery::getSampleBlock( } Block table_sample = metadata_snapshot->getSampleBlock(); + const auto & columns = metadata_snapshot->getColumns(); + auto names_and_types = columns.getOrdinary(); + removeDuplicateColumns(names_and_types); + auto table_expr = std::make_shared(); + table_expr->database_and_table_name = createTableIdentifier(table->getStorageID()); + table_expr->children.push_back(table_expr->database_and_table_name); + TablesWithColumns tables_with_columns; + tables_with_columns.emplace_back(DatabaseAndTableWithAlias(*table_expr, context.getCurrentDatabase()), names_and_types); + + tables_with_columns[0].addHiddenColumns(columns.getMaterialized()); + tables_with_columns[0].addHiddenColumns(columns.getAliases()); + tables_with_columns[0].addHiddenColumns(table->getVirtuals()); + + NameSet source_columns_set; + for (const auto & identifier : query.columns->children) + source_columns_set.insert(identifier->getColumnName()); + TranslateQualifiedNamesVisitor::Data visitor_data(source_columns_set, tables_with_columns); + TranslateQualifiedNamesVisitor visitor(visitor_data); + auto columns_ast = query.columns->clone(); + visitor.visit(columns_ast); + /// Form the block based on the column names from the query Block res; - for (const auto & identifier : query.columns->children) + for (const auto & identifier : columns_ast->children) { std::string current_name = identifier->getColumnName(); diff --git a/src/Parsers/ParserInsertQuery.cpp b/src/Parsers/ParserInsertQuery.cpp index dc25954c71f..50baf7566d1 100644 --- a/src/Parsers/ParserInsertQuery.cpp +++ b/src/Parsers/ParserInsertQuery.cpp @@ -36,7 +36,7 @@ bool ParserInsertQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) ParserToken s_lparen(TokenType::OpeningRoundBracket); ParserToken s_rparen(TokenType::ClosingRoundBracket); ParserIdentifier name_p; - ParserList columns_p(std::make_unique(), std::make_unique(TokenType::Comma), false); + ParserList columns_p(std::make_unique(), std::make_unique(TokenType::Comma), false); ParserFunction table_function_p{false}; ASTPtr database; @@ -189,5 +189,12 @@ bool ParserInsertQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) return true; } +bool ParserInsertElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) +{ + return ParserColumnsMatcher().parse(pos, node, expected) + || ParserQualifiedAsterisk().parse(pos, node, expected) + || ParserAsterisk().parse(pos, node, expected) + || ParserCompoundIdentifier().parse(pos, node, expected); +} } diff --git a/src/Parsers/ParserInsertQuery.h b/src/Parsers/ParserInsertQuery.h index b69bc645c15..b6a199c9d71 100644 --- a/src/Parsers/ParserInsertQuery.h +++ b/src/Parsers/ParserInsertQuery.h @@ -33,4 +33,13 @@ public: ParserInsertQuery(const char * end_) : end(end_) {} }; +/** Insert accepts an identifier and an asterisk with variants. + */ +class ParserInsertElement : public IParserBase +{ +protected: + const char * getName() const override { return "insert element"; } + bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; +}; + } diff --git a/tests/queries/0_stateless/01470_test_insert_select_asterisk.reference b/tests/queries/0_stateless/01470_test_insert_select_asterisk.reference new file mode 100644 index 00000000000..c5d97af6937 --- /dev/null +++ b/tests/queries/0_stateless/01470_test_insert_select_asterisk.reference @@ -0,0 +1,6 @@ +1 0 0 2 +3 0 0 4 +1 0 0 2 +3 0 0 4 +1 0 0 2 +3 0 0 4 diff --git a/tests/queries/0_stateless/01470_test_insert_select_asterisk.sql b/tests/queries/0_stateless/01470_test_insert_select_asterisk.sql new file mode 100644 index 00000000000..607b8a25f82 --- /dev/null +++ b/tests/queries/0_stateless/01470_test_insert_select_asterisk.sql @@ -0,0 +1,18 @@ +DROP TABLE IF EXISTS insert_select_dst; +DROP TABLE IF EXISTS insert_select_src; + +CREATE TABLE insert_select_dst (i int, middle_a int, middle_b int, j int) ENGINE = Log; + +CREATE TABLE insert_select_src (i int, j int) ENGINE = Log; + +INSERT INTO insert_select_src VALUES (1, 2), (3, 4); + +INSERT INTO insert_select_dst(* EXCEPT (middle_a, middle_b)) SELECT * FROM insert_select_src; +INSERT INTO insert_select_dst(insert_select_dst.* EXCEPT (middle_a, middle_b)) SELECT * FROM insert_select_src; +INSERT INTO insert_select_dst(COLUMNS('.*') EXCEPT (middle_a, middle_b)) SELECT * FROM insert_select_src; +INSERT INTO insert_select_dst(insert_select_src.* EXCEPT (middle_a, middle_b)) SELECT * FROM insert_select_src; -- { serverError 47 } + +SELECT * FROM insert_select_dst; + +DROP TABLE IF EXISTS insert_select_dst; +DROP TABLE IF EXISTS insert_select_src;