ClickHouse/dbms/src/TableFunctions/ITableFunctionXDBC.cpp

95 lines
3.7 KiB
C++
Raw Normal View History

2018-09-25 00:21:20 +00:00
#include <type_traits>
#include <ext/scope_guard.h>
#include <DataTypes/DataTypeFactory.h>
#include <Interpreters/evaluateConstantExpression.h>
#include <IO/ReadHelpers.h>
#include <IO/ReadWriteBufferFromHTTP.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTLiteral.h>
#include <Parsers/ParserQueryWithOutput.h>
#include <Parsers/parseQuery.h>
#include <Poco/Net/HTTPRequest.h>
#include <TableFunctions/ITableFunction.h>
#include <TableFunctions/ITableFunctionXDBC.h>
#include <TableFunctions/TableFunctionFactory.h>
#include <Storages/StorageXDBC.h>
2018-09-25 00:21:20 +00:00
#include <Common/Exception.h>
#include <Common/typeid_cast.h>
#include <Core/Defines.h>
namespace DB
{
namespace ErrorCodes
{
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
}
StoragePtr ITableFunctionXDBC::executeImpl(const ASTPtr & ast_function, const Context & context) const
{
const ASTFunction & args_func = typeid_cast<const ASTFunction &>(*ast_function);
if (!args_func.arguments)
throw Exception("Table function '" + getName() + "' must have arguments.", ErrorCodes::LOGICAL_ERROR);
ASTs & args = typeid_cast<ASTExpressionList &>(*args_func.arguments).children;
if (args.size() != 2 && args.size() != 3)
2018-09-25 14:29:44 +00:00
throw Exception("Table function '" + getName() + "' requires 2 or 3 arguments: " + getName() + "('DSN', table) or "+getName()+"('DSN', schema, table)",
2018-09-25 00:21:20 +00:00
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
for (auto i = 0u; i < args.size(); ++i)
args[i] = evaluateConstantExpressionOrIdentifierAsLiteral(args[i], context);
std::string connection_string = "";
std::string schema_name = "";
std::string table_name = "";
if (args.size() == 3)
{
connection_string = static_cast<const ASTLiteral &>(*args[0]).value.safeGet<String>();
schema_name = static_cast<const ASTLiteral &>(*args[1]).value.safeGet<String>();
table_name = static_cast<const ASTLiteral &>(*args[2]).value.safeGet<String>();
} else if (args.size() == 2)
{
connection_string = static_cast<const ASTLiteral &>(*args[0]).value.safeGet<String>();
table_name = static_cast<const ASTLiteral &>(*args[1]).value.safeGet<String>();
}
const auto & config = context.getConfigRef();
/* Infer external table structure */
BridgeHelperPtr helper = createBridgeHelper(config, context.getSettingsRef().http_receive_timeout.value, connection_string);
helper->startBridgeSync();
Poco::URI columns_info_uri = helper->getColumnsInfoURI();
columns_info_uri.addQueryParameter("connection_string", connection_string);
if (!schema_name.empty())
columns_info_uri.addQueryParameter("schema", schema_name);
columns_info_uri.addQueryParameter("table", table_name);
ReadWriteBufferFromHTTP buf(columns_info_uri, Poco::Net::HTTPRequest::HTTP_POST, nullptr);
std::string columns_info;
readStringBinary(columns_info, buf);
NamesAndTypesList columns = NamesAndTypesList::parse(columns_info);
auto result = std::make_shared<StorageXDBC>(table_name, schema_name, table_name, ColumnsDescription{columns}, context, helper);
2018-09-25 00:21:20 +00:00
if(!result)
2018-09-25 14:29:44 +00:00
throw Exception("Failed to instantiate storage from table function " + getName());
2018-09-25 00:21:20 +00:00
result->startup();
return result;
}
2018-09-25 14:29:44 +00:00
void registerTableFunctionJDBC(TableFunctionFactory & factory)
{
factory.registerFunction<TableFunctionJDBC>();
}
void registerTableFunctionODBC(TableFunctionFactory & factory)
2018-09-25 14:29:44 +00:00
{
factory.registerFunction<TableFunctionODBC>();
2018-09-25 14:29:44 +00:00
}
2018-09-25 00:21:20 +00:00
}