1#include <Common/typeid_cast.h>
2#include <Common/Exception.h>
3
4#include <Core/Block.h>
5#include <Storages/StorageValues.h>
6#include <DataTypes/DataTypeTuple.h>
7
8#include <Parsers/ASTExpressionList.h>
9#include <Parsers/ASTLiteral.h>
10#include <Parsers/ASTFunction.h>
11
12#include <TableFunctions/ITableFunction.h>
13#include <TableFunctions/TableFunctionValues.h>
14#include <TableFunctions/TableFunctionFactory.h>
15#include <TableFunctions/parseColumnsListForTableFunction.h>
16
17#include <Interpreters/convertFieldToType.h>
18#include <Interpreters/evaluateConstantExpression.h>
19#include "registerTableFunctions.h"
20
21
22namespace DB
23{
24
25namespace ErrorCodes
26{
27 extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
28}
29
30static void parseAndInsertValues(MutableColumns & res_columns, const ASTs & args, const Block & sample_block, const Context & context)
31{
32 if (res_columns.size() == 1) /// Parsing arguments as Fields
33 {
34 for (size_t i = 1; i < args.size(); ++i)
35 {
36 const auto & [value_field, value_type_ptr] = evaluateConstantExpression(args[i], context);
37
38 Field value = convertFieldToType(value_field, *sample_block.getByPosition(0).type, value_type_ptr.get());
39 res_columns[0]->insert(value);
40 }
41 }
42 else /// Parsing arguments as Tuples
43 {
44 for (size_t i = 1; i < args.size(); ++i)
45 {
46 const auto & [value_field, value_type_ptr] = evaluateConstantExpression(args[i], context);
47 const DataTypes & value_types_tuple = typeid_cast<const DataTypeTuple *>(value_type_ptr.get())->getElements();
48 const Tuple & value_tuple = value_field.safeGet<Tuple>();
49
50 if (value_tuple.size() != sample_block.columns())
51 throw Exception("Values size should match with number of columns", ErrorCodes::LOGICAL_ERROR);
52
53 for (size_t j = 0; j < value_tuple.size(); ++j)
54 {
55 Field value = convertFieldToType(value_tuple[j], *sample_block.getByPosition(j).type, value_types_tuple[j].get());
56 res_columns[j]->insert(value);
57 }
58 }
59 }
60}
61
62StoragePtr TableFunctionValues::executeImpl(const ASTPtr & ast_function, const Context & context, const std::string & table_name) const
63{
64 ASTs & args_func = ast_function->children;
65
66 if (args_func.size() != 1)
67 throw Exception("Table function '" + getName() + "' must have arguments.", ErrorCodes::LOGICAL_ERROR);
68
69 ASTs & args = args_func.at(0)->children;
70
71 if (args.size() < 2)
72 throw Exception("Table function '" + getName() + "' requires 2 or more arguments: structure and values.",
73 ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
74
75 /// Parsing first argument as table structure and creating a sample block
76 std::string structure = args[0]->as<ASTLiteral &>().value.safeGet<String>();
77
78 ColumnsDescription columns = parseColumnsListFromString(structure, context);
79
80 Block sample_block;
81 for (const auto & name_type : columns.getOrdinary())
82 sample_block.insert({ name_type.type->createColumn(), name_type.type, name_type.name });
83
84 MutableColumns res_columns = sample_block.cloneEmptyColumns();
85
86 /// Parsing other arguments as values and inserting them into columns
87 parseAndInsertValues(res_columns, args, sample_block, context);
88
89 Block res_block = sample_block.cloneWithColumns(std::move(res_columns));
90
91 auto res = StorageValues::create(getDatabaseName(), table_name, columns, res_block);
92 res->startup();
93 return res;
94}
95
96void registerTableFunctionValues(TableFunctionFactory & factory)
97{
98 factory.registerFunction<TableFunctionValues>(TableFunctionFactory::CaseInsensitive);
99}
100
101}
102