Fixed issue #3540 (in progress)

This commit is contained in:
Alexey Milovidov 2019-05-17 00:09:06 +03:00
parent 5352b53671
commit dd9e993a87
3 changed files with 41 additions and 13 deletions

View File

@ -367,6 +367,6 @@ if (ENABLE_TESTS AND USE_GTEST)
# attach all dbms gtest sources
grep_gtest_sources(${ClickHouse_SOURCE_DIR}/dbms dbms_gtest_sources)
add_executable(unit_tests_dbms ${dbms_gtest_sources})
target_link_libraries(unit_tests_dbms PRIVATE ${GTEST_BOTH_LIBRARIES} dbms clickhouse_common_zookeeper)
target_link_libraries(unit_tests_dbms PRIVATE ${GTEST_BOTH_LIBRARIES} clickhouse_functions dbms clickhouse_common_zookeeper)
add_check(unit_tests_dbms)
endif ()

View File

@ -12,15 +12,25 @@
#include <Interpreters/Context.h>
#include <Databases/DatabaseMemory.h>
#include <Storages/StorageMemory.h>
#include <Functions/registerFunctions.h>
using namespace DB;
void check(const std::string & query, const std::string & expected, const Context & context, const NamesAndTypesList & columns)
{
ParserSelectQuery parser;
ASTPtr ast = parseQuery(parser, query, 1000);
std::string transformed_query = transformQueryForExternalDatabase(*ast, columns, IdentifierQuotingStyle::DoubleQuotes, "test", "table", context);
EXPECT_EQ(transformed_query, expected);
}
TEST(transformQueryForExternalDatabase, InWithSingleElement)
{
using namespace DB;
std::string query = "SELECT column FROM test.table WHERE 1 IN (1)"; /// Parentheses around rhs of IN must be retained after transformation.
ParserSelectQuery parser;
ASTPtr ast = parseQuery(parser, query, 1000);
registerFunctions();
Context context = Context::createGlobal();
DatabasePtr database = std::make_shared<DatabaseMemory>("test");
@ -29,7 +39,6 @@ TEST(transformQueryForExternalDatabase, InWithSingleElement)
context.addDatabase("test", database);
context.setCurrentDatabase("test");
std::string transformed_query = transformQueryForExternalDatabase(*ast, columns, IdentifierQuotingStyle::DoubleQuotes, "test", "table", context);
EXPECT_EQ(transformed_query, "SELECT \"column\" FROM \"test\".\"table\" WHERE 1 IN (1)");
check("SELECT column FROM test.table WHERE 1 IN (1)", "SELECT \"column\" FROM \"test\".\"table\" WHERE 1 IN (1)", context, columns);
check("SELECT column FROM test.table WHERE column IN (1, 2)", "SELECT \"column\" FROM \"test\".\"table\" WHERE \"column\" IN (1, 2)", context, columns);
}

View File

@ -16,6 +16,11 @@
namespace DB
{
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
}
static void replaceConstFunction(IAST & node, const Context & context, const NamesAndTypesList & all_columns)
{
for (size_t i = 0; i < node.children.size(); ++i)
@ -44,19 +49,33 @@ static bool isCompatible(const IAST & node)
{
if (const auto * function = node.as<ASTFunction>())
{
if (function->parameters)
return false;
if (!function->arguments)
throw Exception("Logical error: function->arguments is not set", ErrorCodes::LOGICAL_ERROR);
String name = function->name;
if (!(name == "and"
|| name == "or"
|| name == "not"
|| name == "equals"
|| name == "notEquals"
|| name == "less"
|| name == "greater"
|| name == "lessOrEquals"
|| name == "greaterOrEquals"
|| name == "like"
|| name == "notLike"
|| name == "in"
|| name == "greater"
|| name == "less"
|| name == "lessOrEquals"
|| name == "greaterOrEquals"))
|| name == "notIn"
|| name == "tuple"))
return false;
/// A tuple with zero or one elements is represented by a function tuple(x) and is not compatible,
/// but a normal tuple with more than one element is represented as a parenthesed expression (x, y) and is perfectly compatible.
if (name == "tuple" && function->arguments->children.size() <= 1)
return false;
for (const auto & expr : function->arguments->children)