Skip to content

Commit d070906

Browse files
authored
Merge pull request #31 from pakapor/bugfix-insertSpaceColumn
Fix Insert into column name with space
2 parents 067b04d + 46396a6 commit d070906

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

clickhouse/client.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,25 @@ void Client::Impl::ExecuteQuery(Query query) {
201201
}
202202
}
203203

204+
std::string NameToQueryString(const std::string &input)
205+
{
206+
std::string output;
207+
output.reserve(input.size() + 2);
208+
output += '`';
209+
210+
for (const auto & c : input) {
211+
if (c == '`') {
212+
//escape ` with ``
213+
output.append("``");
214+
} else {
215+
output.push_back(c);
216+
}
217+
}
218+
219+
output += '`';
220+
return output;
221+
}
222+
204223
void Client::Impl::Insert(const std::string& table_name, const Block& block) {
205224
if (options_.ping_before_query) {
206225
RetryGuard([this]() { Ping(); });
@@ -211,7 +230,7 @@ void Client::Impl::Insert(const std::string& table_name, const Block& block) {
211230

212231
// Enumerate all fields
213232
for (unsigned int i = 0; i < block.GetColumnCount(); i++) {
214-
fields.push_back(block.GetColumnName(i));
233+
fields.push_back(NameToQueryString(block.GetColumnName(i)));
215234
}
216235

217236
std::stringstream fields_section;

ut/client_ut.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,54 @@ TEST_P(ClientCase, Decimal) {
716716
});
717717
}
718718

719+
// Test special chars in names
720+
TEST_P(ClientCase, ColEscapeNameTest) {
721+
client_->Execute(R"sql(DROP TABLE IF EXISTS test_clickhouse_cpp."col_escape_""name_test";)sql");
722+
723+
client_->Execute(R"sql(CREATE TABLE IF NOT EXISTS test_clickhouse_cpp."col_escape_""name_test" ("test space" UInt64, "test "" quote" UInt64, "test ""`'[]&_\ all" UInt64) ENGINE = Memory)sql");
724+
725+
auto col1 = std::make_shared<ColumnUInt64>();
726+
col1->Append(1);
727+
col1->Append(2);
728+
auto col2 = std::make_shared<ColumnUInt64>();
729+
col2->Append(4);
730+
col2->Append(8);
731+
auto col3 = std::make_shared<ColumnUInt64>();
732+
col3->Append(16);
733+
col3->Append(32);
734+
735+
static const std::string column_names[] = {
736+
"test space",
737+
R"sql(test " quote)sql",
738+
R"sql(test "`'[]&_\ all)sql"
739+
};
740+
static const auto columns_count = sizeof(column_names)/sizeof(column_names[0]);
741+
742+
Block block;
743+
block.AppendColumn(column_names[0], col1);
744+
block.AppendColumn(column_names[1], col2);
745+
block.AppendColumn(column_names[2], col3);
746+
747+
client_->Insert(R"sql(test_clickhouse_cpp."col_escape_""name_test")sql", block);
748+
client_->Select(R"sql(SELECT * FROM test_clickhouse_cpp."col_escape_""name_test")sql", [] (const Block& sblock)
749+
{
750+
int row = sblock.GetRowCount();
751+
if (row <= 0) {return;}
752+
ASSERT_EQ(columns_count, sblock.GetColumnCount());
753+
for (size_t i = 0; i < columns_count; ++i) {
754+
EXPECT_EQ(column_names[i], sblock.GetColumnName(i));
755+
}
756+
757+
EXPECT_EQ(row, 2);
758+
EXPECT_EQ(sblock[0]->As<ColumnUInt64>()->At(0), 1u);
759+
EXPECT_EQ(sblock[0]->As<ColumnUInt64>()->At(1), 2u);
760+
EXPECT_EQ(sblock[1]->As<ColumnUInt64>()->At(0), 4u);
761+
EXPECT_EQ(sblock[1]->As<ColumnUInt64>()->At(1), 8u);
762+
EXPECT_EQ(sblock[2]->As<ColumnUInt64>()->At(0), 16u);
763+
EXPECT_EQ(sblock[2]->As<ColumnUInt64>()->At(1), 32u);
764+
});
765+
}
766+
719767
// Test roundtrip of DateTime64 values
720768
TEST_P(ClientCase, DateTime64) {
721769
const auto & server_info = client_->GetServerInfo();

0 commit comments

Comments
 (0)