diff --git a/src/Planner/PlannerActionsVisitor.cpp b/src/Planner/PlannerActionsVisitor.cpp index 43177fc73c0..a420088e3b4 100644 --- a/src/Planner/PlannerActionsVisitor.cpp +++ b/src/Planner/PlannerActionsVisitor.cpp @@ -36,6 +36,10 @@ namespace DB { +namespace Setting +{ + extern const SettingsBool enable_named_columns_in_function_tuple; +} namespace ErrorCodes { @@ -178,6 +182,33 @@ public: break; } + if (planner_context.getQueryContext()->getSettingsRef()[Setting::enable_named_columns_in_function_tuple]) + { + /// Function "tuple" which generates named tuple should use argument aliases to construct its name. + if (function_node.getFunctionName() == "tuple") + { + if (const DataTypeTuple * type_tuple = typeid_cast(function_node.getResultType().get())) + { + if (type_tuple->haveExplicitNames()) + { + const auto & names = type_tuple->getElementNames(); + size_t size = names.size(); + WriteBufferFromOwnString s; + s << "tuple("; + for (size_t i = 0; i < size; ++i) + { + if (i != 0) + s << ", "; + s << backQuoteIfNeed(names[i]); + } + s << ")"; + result = s.str(); + break; + } + } + } + } + String in_function_second_argument_node_name; if (isNameOfInFunction(function_node.getFunctionName())) diff --git a/tests/queries/0_stateless/03240_insert_select_named_tuple.reference b/tests/queries/0_stateless/03240_insert_select_named_tuple.reference new file mode 100644 index 00000000000..8c3cb5b8425 --- /dev/null +++ b/tests/queries/0_stateless/03240_insert_select_named_tuple.reference @@ -0,0 +1,3 @@ +1 ('dete','ok') ('dete','ok') +{"id":1,"a":{"col_a":"dete","type":"ok"},"b":{"col_b":"dete","type":"ok"}} +{"id":1,"a":{"col_a":"dete","type":"ok"},"b":{"col_b":"dete","type":"ok"}} diff --git a/tests/queries/0_stateless/03240_insert_select_named_tuple.sql b/tests/queries/0_stateless/03240_insert_select_named_tuple.sql new file mode 100644 index 00000000000..c3e12db4e0e --- /dev/null +++ b/tests/queries/0_stateless/03240_insert_select_named_tuple.sql @@ -0,0 +1,22 @@ +SET enable_analyzer = 1; +SET enable_named_columns_in_function_tuple = 1; + +DROP TABLE IF EXISTS src; +DROP TABLE IF EXISTS dst; + +CREATE TABLE src (id UInt32, type String, data String) ENGINE=MergeTree ORDER BY tuple(); +CREATE TABLE dst (id UInt32, a Tuple (col_a Nullable(String), type String), b Tuple (col_b Nullable(String), type String)) ENGINE = MergeTree ORDER BY id; + +INSERT INTO src VALUES (1, 'ok', 'data'); +INSERT INTO dst (id, a, b) SELECT id, tuple(replaceAll(data, 'a', 'e') AS col_a, type) AS a, tuple(replaceAll(data, 'a', 'e') AS col_b, type) AS b FROM src; +SELECT * FROM dst; + +DROP TABLE src; +DROP TABLE dst; + +DROP TABLE IF EXISTS src; +CREATE TABLE src (id UInt32, type String, data String) ENGINE=MergeTree ORDER BY tuple(); +INSERT INTO src VALUES (1, 'ok', 'data'); +SELECT id, tuple(replaceAll(data, 'a', 'e') AS col_a, type) AS a, tuple(replaceAll(data, 'a', 'e') AS col_b, type) AS b FROM cluster(test_cluster_two_shards, currentDatabase(), src) SETTINGS prefer_localhost_replica=0 FORMAT JSONEachRow; + +DROP TABLE src;