Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion clickhouse/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,29 @@ std::string NameToQueryString(const std::string &input)
return output;
}

std::string TableNameToQueryString(const std::string& input)
{
if (input.size() >= 2 && input.front() == '`' && input.back() == '`') {
return input;
}

std::string output;
size_t start = 0;
bool first = true;
for (size_t i = 0; i <= input.size(); ++i) {
if (i == input.size() || input[i] == '.') {
if (!first) {
output.push_back('.');
}
output += NameToQueryString(input.substr(start, i - start));
first = false;
start = i + 1;
}
}

return output;
}

void Client::Impl::Insert(const std::string& table_name, const std::string& query_id, const Block& block) {
if (state_ == State::Inserting) {
throw ValidationError("cannot execute query while inserting, use SendInsertData instead");
Expand All @@ -509,7 +532,9 @@ void Client::Impl::Insert(const std::string& table_name, const std::string& quer
}
}

Query query("INSERT INTO " + table_name + " ( " + fields_section.str() + " ) VALUES", query_id);
Query query(
"INSERT INTO " + TableNameToQueryString(table_name) + " ( " + fields_section.str() + " ) VALUES",
query_id);
SendQuery(query);

// Wait for a data packet and return
Expand Down
3 changes: 3 additions & 0 deletions clickhouse/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,9 @@ class Client {
bool IsSelecting() const;

/// Intends for insert block of data into a table \p table_name.
/// \p table_name is a bare table identifier, or a qualified \c database.table name.
/// Each identifier part is quoted automatically. Pass an already backtick-quoted
/// identifier to use it verbatim (for example a table name that contains a dot).
void Insert(const std::string& table_name, const Block& block);
void Insert(const std::string& table_name, const std::string& query_id, const Block& block);

Expand Down
29 changes: 29 additions & 0 deletions ut/client_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,35 @@ TEST_P(ClientCase, LowCardinality) {
ASSERT_EQ(total_rows, data.size());
}

TEST_P(ClientCase, InsertQuotesBareTableName) {
const std::string hyphenated_table = "test_clickhouse_cpp_my-table";

client_->Execute("DROP TABLE IF EXISTS `" + hyphenated_table + "`");
client_->Execute("CREATE TABLE `" + hyphenated_table + "` (id Int64) ENGINE = Memory");

Block block;
auto col = std::make_shared<ColumnInt64>();
col->Append(42);
block.AppendColumn("id", col);
block.RefreshRowCount();

client_->Insert(hyphenated_table, block);

int64_t value = 0;
client_->Select(
"SELECT id FROM `" + hyphenated_table + "`",
[&value](const Block& result) {
if (result.GetRowCount() == 0) {
return;
}

value = result[0]->As<ColumnInt64>()->At(0);
});

EXPECT_EQ(value, 42);
client_->Execute("DROP TABLE IF EXISTS `" + hyphenated_table + "`");
}

TEST_P(ClientCase, LowCardinality_InsertAfterClear) {
// User can successfully insert values after invoking Clear() on LC column.
Block block;
Expand Down