mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Merge pull request #57857 from canhld94/ch_external_table_enum
Allow declaring enum in external table structure
This commit is contained in:
commit
0067ef0f97
@ -17,6 +17,9 @@
|
||||
|
||||
#include <Core/ExternalTable.h>
|
||||
#include <Poco/Net/MessageHeader.h>
|
||||
#include <Parsers/ASTNameTypePair.h>
|
||||
#include <Parsers/ParserCreateQuery.h>
|
||||
#include <Parsers/parseQuery.h>
|
||||
#include <base/scope_guard.h>
|
||||
|
||||
|
||||
@ -28,6 +31,18 @@ namespace ErrorCodes
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
/// Parsing a list of types with `,` as separator. For example, `Int, Enum('foo'=1,'bar'=2), Double`
|
||||
/// Used in `parseStructureFromTypesField`
|
||||
class ParserTypeList : public IParserBase
|
||||
{
|
||||
protected:
|
||||
const char * getName() const override { return "type pair list"; }
|
||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
|
||||
{
|
||||
return ParserList(std::make_unique<ParserDataType>(), std::make_unique<ParserToken>(TokenType::Comma), false)
|
||||
.parse(pos, node, expected);
|
||||
}
|
||||
};
|
||||
|
||||
ExternalTableDataPtr BaseExternalTable::getData(ContextPtr context)
|
||||
{
|
||||
@ -55,23 +70,36 @@ void BaseExternalTable::clear()
|
||||
|
||||
void BaseExternalTable::parseStructureFromStructureField(const std::string & argument)
|
||||
{
|
||||
std::vector<std::string> vals;
|
||||
splitInto<' ', ','>(vals, argument, true);
|
||||
ParserNameTypePairList parser;
|
||||
const auto * pos = argument.data();
|
||||
String error;
|
||||
ASTPtr columns_list_raw = tryParseQuery(parser, pos, pos + argument.size(), error, false, "", false, DBMS_DEFAULT_MAX_QUERY_SIZE, DBMS_DEFAULT_MAX_PARSER_DEPTH, DBMS_DEFAULT_MAX_PARSER_BACKTRACKS, true);
|
||||
|
||||
if (vals.size() % 2 != 0)
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Odd number of attributes in section structure: {}", vals.size());
|
||||
if (!columns_list_raw)
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: {}", error);
|
||||
|
||||
for (size_t i = 0; i < vals.size(); i += 2)
|
||||
structure.emplace_back(vals[i], vals[i + 1]);
|
||||
for (auto & child : columns_list_raw->children)
|
||||
{
|
||||
auto * column = child->as<ASTNameTypePair>();
|
||||
if (column)
|
||||
structure.emplace_back(column->name, column->type->getColumnNameWithoutAlias());
|
||||
else
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: expected column definition, got {}", child->formatForErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void BaseExternalTable::parseStructureFromTypesField(const std::string & argument)
|
||||
{
|
||||
std::vector<std::string> vals;
|
||||
splitInto<' ', ','>(vals, argument, true);
|
||||
ParserTypeList parser;
|
||||
const auto * pos = argument.data();
|
||||
String error;
|
||||
ASTPtr type_list_raw = tryParseQuery(parser, pos, pos+argument.size(), error, false, "", false, DBMS_DEFAULT_MAX_QUERY_SIZE, DBMS_DEFAULT_MAX_PARSER_DEPTH, DBMS_DEFAULT_MAX_PARSER_BACKTRACKS, true);
|
||||
|
||||
for (size_t i = 0; i < vals.size(); ++i)
|
||||
structure.emplace_back("_" + toString(i + 1), vals[i]);
|
||||
if (!type_list_raw)
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: {}", error);
|
||||
|
||||
for (size_t i = 0; i < type_list_raw->children.size(); ++i)
|
||||
structure.emplace_back("_" + toString(i + 1), type_list_raw->children[i]->getColumnNameWithoutAlias());
|
||||
}
|
||||
|
||||
void BaseExternalTable::initSampleBlock()
|
||||
|
@ -0,0 +1,4 @@
|
||||
foo 1
|
||||
bar 2
|
||||
foo 1
|
||||
bar 2
|
12
tests/queries/0_stateless/02935_external_table_enum_type.sh
Executable file
12
tests/queries/0_stateless/02935_external_table_enum_type.sh
Executable file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
# shellcheck source=../shell_config.sh
|
||||
. "$CURDIR"/../shell_config.sh
|
||||
|
||||
http_url="http://${CLICKHOUSE_HOST}:${CLICKHOUSE_PORT_HTTP}/?"
|
||||
|
||||
curl -s "${http_url}temp_structure=x+Enum8('foo'%3D1,'bar'%3D2),y+Int" -F "$(printf 'temp='"foo"'\t1');filename=data1" -F "query=SELECT * FROM temp"
|
||||
curl -s "${http_url}temp_types=Enum8('foo'%3D1,'bar'%3D2),Int" -F "$(printf 'temp='"bar"'\t2');filename=data1" -F "query=SELECT * FROM temp"
|
||||
echo -ne 'foo\t1' | ${CLICKHOUSE_CLIENT} --query="select * from tmp" --external --file=- --name=tmp --structure="x Enum8('foo'=1,'bar'=2),y Int"
|
||||
echo -ne 'bar\t2' | ${CLICKHOUSE_CLIENT} --query="select * from tmp" --external --file=- --name=tmp --types="Enum8('foo'=1,'bar'=2),Int"
|
@ -0,0 +1 @@
|
||||
Hello world
|
7
tests/queries/0_stateless/03018_external_with_complex_data_types.sh
Executable file
7
tests/queries/0_stateless/03018_external_with_complex_data_types.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
# shellcheck source=../shell_config.sh
|
||||
. "$CURDIR"/../shell_config.sh
|
||||
|
||||
${CLICKHOUSE_CLIENT} --external --file <(echo "Hello, world") --name test --format CSV --structure "x Enum('Hello' = 1, 'world' = 2), y String" --query "SELECT * FROM test"
|
Loading…
Reference in New Issue
Block a user