forked from ClickHouse/ClickHouse
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathITableFunction.cpp
More file actions
99 lines (80 loc) · 3.43 KB
/
Copy pathITableFunction.cpp
File metadata and controls
99 lines (80 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <Access/ContextAccess.h>
#include <TableFunctions/ITableFunction.h>
#include <Storages/StorageFactory.h>
#include <Storages/StorageTableFunction.h>
#include <Access/Common/AccessFlags.h>
#include <Common/ProfileEvents.h>
#include <TableFunctions/TableFunctionFactory.h>
#include <Interpreters/Context.h>
namespace ProfileEvents
{
extern const Event TableFunctionExecute;
}
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;;
}
namespace DB
{
const char * ITableFunction::getNonClusteredStorageEngineName() const
{
throw Exception(ErrorCodes::LOGICAL_ERROR, "Not implemented");
}
std::optional<AccessTypeObjects::Source> ITableFunction::getSourceAccessObject() const
{
if (isClusterFunction())
return StorageFactory::instance().getSourceAccessObject(getNonClusteredStorageEngineName());
return StorageFactory::instance().getSourceAccessObject(getStorageEngineName());
}
void ITableFunction::checkSourceAccess(ContextPtr context, bool is_insert_query) const
{
if (const auto access_object = getSourceAccessObject())
{
AccessType type_to_check = AccessType::READ;
if (is_insert_query)
type_to_check = AccessType::WRITE;
context->getAccess()->checkAccessWithFilter(type_to_check, toStringSource(*access_object), getFunctionURINormalized());
}
}
ColumnsDescription ITableFunction::getActualTableStructureWithAccess(ContextPtr context, bool is_insert_query) const
{
/// Resolving table structure is always a read operation.
checkSourceAccess(context, /*is_insert_query*/ false);
return getActualTableStructure(context, is_insert_query);
}
StoragePtr ITableFunction::execute(const ASTPtr & ast_function, ContextPtr context, const std::string & table_name,
ColumnsDescription cached_columns, bool use_global_context, bool is_insert_query) const
{
ProfileEvents::increment(ProfileEvents::TableFunctionExecute);
checkSourceAccess(context, is_insert_query);
auto table_function_properties = TableFunctionFactory::instance().tryGetProperties(getName());
if (is_insert_query || !(table_function_properties && table_function_properties->allow_readonly))
context->checkAccess(AccessType::CREATE_TEMPORARY_TABLE);
auto context_to_use = use_global_context ? context->getGlobalContext() : context;
if (cached_columns.empty())
return executeImpl(ast_function, context, table_name, std::move(cached_columns), is_insert_query);
if (hasStaticStructure() && cached_columns == getActualTableStructure(context, is_insert_query))
return executeImpl(ast_function, context_to_use, table_name, std::move(cached_columns), is_insert_query);
auto this_table_function = shared_from_this();
auto get_storage = [=]() -> StoragePtr
{
return this_table_function->executeImpl(ast_function, context_to_use, table_name, cached_columns, is_insert_query);
};
/// It will request actual table structure and create underlying storage lazily
return std::make_shared<StorageTableFunctionProxy>(StorageID(getDatabaseName(), table_name), std::move(get_storage),
std::move(cached_columns), needStructureConversion());
}
String ITableFunction::getFunctionURINormalized() const
{
try
{
Poco::URI uri(getFunctionURI());
uri.normalize();
return uri.toString();
}
catch (const Poco::Exception &)
{
return "";
}
}
}