提交 7254478f 编写于 作者: V Vladimir Chebotarev 提交者: alexey-milovidov

functions: Remote mode for hasColumnInTable. [#CHEBOTAREV-9]

上级 dd0905e9
......@@ -16,10 +16,12 @@
#include <DataTypes/DataTypeTuple.h>
#include <DataTypes/DataTypesNumber.h>
#include <Functions/FunctionFactory.h>
#include <Interpreters/Cluster.h>
#include <Interpreters/Context.h>
#include <Interpreters/Set.h>
#include <Storages/IStorage.h>
#include <Common/typeid_cast.h>
#include <TableFunctions/getStructureOfRemoteTable.h>
namespace DB
......@@ -1666,18 +1668,12 @@ public:
/** Usage:
* hasColumnInTable('database', 'table', 'column')
* hasColumnInTable(['hostname'[, 'username'[, 'password']],] 'database', 'table', 'column')
*/
class FunctionHasColumnInTable : public IFunction
{
public:
static constexpr auto name = "hasColumnInTable";
size_t getNumberOfArguments() const override
{
return 3;
}
static FunctionPtr create(const Context & context)
{
return std::make_shared<FunctionHasColumnInTable>(context.getGlobalContext());
......@@ -1687,6 +1683,15 @@ public:
{
}
bool isVariadic() const override
{
return true;
}
size_t getNumberOfArguments() const override
{
return 0;
}
String getName() const override
{
return name;
......@@ -1743,8 +1748,12 @@ void FunctionVisibleWidth::executeImpl(Block & block, const ColumnNumbers & argu
void FunctionHasColumnInTable::getReturnTypeAndPrerequisitesImpl(
const ColumnsWithTypeAndName & arguments, DataTypePtr & out_return_type, ExpressionActions::Actions & out_prerequisites)
{
static const std::string arg_pos_description[] = {"First", "Second", "Third"};
for (size_t i = 0; i < getNumberOfArguments(); ++i)
if (arguments.size() < 3 || arguments.size() > 6)
throw Exception{"Invalid number of arguments for function " + getName(),
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH};
static const std::string arg_pos_description[] = {"First", "Second", "Third", "Fourth", "Fifth", "Sixth"};
for (size_t i = 0; i < arguments.size(); ++i)
{
const ColumnWithTypeAndName & argument = arguments[i];
......@@ -1768,12 +1777,40 @@ void FunctionHasColumnInTable::executeImpl(Block & block, const ColumnNumbers &
return const_column->getData();
};
const String & database_name = get_string_from_block(arguments[0]);
const String & table_name = get_string_from_block(arguments[1]);
const String & column_name = get_string_from_block(arguments[2]);
size_t arg = 0;
const String * host_name = nullptr;
const String * user_name = nullptr;
const String * password = nullptr;
if (arguments.size() > 3)
{
host_name = &get_string_from_block(arguments[arg++]);
}
if (arguments.size() > 4)
{
user_name = &get_string_from_block(arguments[arg++]);
}
if (arguments.size() > 5)
{
password = &get_string_from_block(arguments[arg++]);
}
const String & database_name = get_string_from_block(arguments[arg++]);
const String & table_name = get_string_from_block(arguments[arg++]);
const String & column_name = get_string_from_block(arguments[arg++]);
const StoragePtr & table = global_context.getTable(database_name, table_name);
const bool has_column = table->hasColumn(column_name);
bool has_column;
if (host_name == nullptr)
{
const StoragePtr & table = global_context.getTable(database_name, table_name);
has_column = table->hasColumn(column_name);
}
else
{
std::vector<std::vector<String>> host_names = {{ *host_name }};
auto cluster = std::make_shared<Cluster>(global_context.getSettings(), host_names, user_name != nullptr ? *user_name : "default", password != nullptr ? *password : "");
auto names_and_types_list = std::make_shared<NamesAndTypesList>(getStructureOfRemoteTable(*cluster, database_name, table_name, global_context));
const auto & names = names_and_types_list->getNames();
has_column = std::find(names.begin(), names.end(), column_name) != names.end();
}
block.safeGetByPosition(result).column = std::make_shared<ColumnConstUInt8>(block.rows(), has_column);
}
......
......@@ -4,13 +4,20 @@ CREATE TABLE test.has_column_in_table (i Int64, s String, nest Nested(x UInt8, y
/* existing column */
SELECT hasColumnInTable('test', 'has_column_in_table', 'i');
SELECT hasColumnInTable('localhost', 'test', 'has_column_in_table', 'i');
SELECT hasColumnInTable('test', 'has_column_in_table', 's');
SELECT hasColumnInTable('localhost', 'test', 'has_column_in_table', 's');
SELECT hasColumnInTable('test', 'has_column_in_table', 'nest.x');
SELECT hasColumnInTable('localhost', 'test', 'has_column_in_table', 'nest.x');
SELECT hasColumnInTable('test', 'has_column_in_table', 'nest.y');
SELECT hasColumnInTable('localhost', 'test', 'has_column_in_table', 'nest.y');
/* not existing column */
SELECT hasColumnInTable('test', 'has_column_in_table', 'nest');
SELECT hasColumnInTable('localhost', 'test', 'has_column_in_table', 'nest');
SELECT hasColumnInTable('test', 'has_column_in_table', 'nest.not_existing');
SELECT hasColumnInTable('localhost', 'test', 'has_column_in_table', 'nest.not_existing');
SELECT hasColumnInTable('test', 'has_column_in_table', 'not_existing');
SELECT hasColumnInTable('localhost', 'test', 'has_column_in_table', 'not_existing');
DROP TABLE test.has_column_in_table;
......@@ -50,10 +50,10 @@ isNaN(x)
~~~~~~~~
Accepts Float32 and Float64 and returns UInt8 equal to 1 if the argument is a NaN, otherwise 0.
hasColumnInTable('database', 'table', 'column')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hasColumnInTable(['hostname'[, 'username'[, 'password']],] 'database', 'table', 'column')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Accepts constant String columns - database name, table name and column name. Returns constant UInt8 value, equal to 1 if column exists,
otherwise 0.
otherwise 0. If hostname is specified, the check will proceed on remote host.
If table doesn't exist than exception is thrown.
For elements of nested data structure function checks existence of column. For nested data structure 0 is returned.
......
......@@ -50,10 +50,10 @@ isNaN(x)
~~~~~~~~
Принимает Float32 или Float64 и возвращает UInt8, равный 1, если аргумент является NaN, иначе 0.
hasColumnInTable('database', 'table', 'column')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hasColumnInTable(['hostname'[, 'username'[, 'password']],] 'database', 'table', 'column')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Принимает константные строки - имя базы данных, имя таблицы и название столбца. Возвращает константное выражение типа UInt8, равное 1,
если есть столбец, иначе 0.
если есть столбец, иначе 0. Если задан параметр hostname, проверка будет выполнена на удалённом сервере.
Функция кидает исключение, если таблица не существует.
Для элементов вложенной структуры данных функция проверяет существование столбца. Для самой же вложенной структуры данных функция возвращает 0.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册