ClickHouse / clickhouse-cpp

C++ client library for ClickHouse
Apache License 2.0
305 stars 159 forks source link

issue using c++ API #319

Closed gdcocchi closed 1 year ago

gdcocchi commented 1 year ago

Hi, I'm new to clickhouse so I'm testing it and seems very fast. But I'm facing a weird issue during the data retrieving from a table, using the c++ API. I have compiled the c++ libs cheking out the v2.4.0 tag. The code I'm running is the following one:

#include <iostream>
#include <string>
#include <clickhouse/client.h>

using namespace clickhouse;
using namespace std;

void create(Client& client)
{
    printf("create started...\n");

    client.Execute("CREATE TABLE IF NOT EXISTS default.tbl_test (id UInt16, fno UInt64, fname String, ftype String) ENGINE = MergeTree PRIMARY KEY (id, fno, fname, ftype)");

    auto id = std::make_shared<ColumnUInt16>();
    auto fno = std::make_shared<ColumnUInt64>();
    auto fname = std::make_shared<ColumnString>();
    auto ftype = std::make_shared<ColumnString>();

    for (uint16_t i = 0; i < 2; i++)
    {
        for(uint64_t j = 0; j < 3; j++)
        {
            id->Append(i);
            fno->Append(j);
            fname->Append("field_name_" + to_string(i) + "-" + to_string(j));
            ftype->Append("field_type_" + to_string(i) + "-" + to_string(j));
        }
    }

    Block block;
    block.AppendColumn("id"  , id);
    block.AppendColumn("fno", fno);
    block.AppendColumn("fname", fname);
    block.AppendColumn("ftype", ftype);
    client.Insert("default.tbl_test", block);
    client.Execute("OPTIMIZE TABLE default.tbl_test FINAL DEDUPLICATE");
    printf("create finished...\n");
}

void display(Client& client)
{
    printf("display started...\n");
    client.Select("SELECT id, fno, fname, ftype FROM default.tbl_test", [] (const Block& block)
        {
            if (block.GetRowCount() > 0)
            {
                std::cout << "ROW count: " << block.GetRowCount() << "\n";
                for (size_t i = 0; i < block.GetRowCount(); ++i)
                {
                    std::cout << (*block[0]->As<ColumnUInt16>())[i] << " ";
                    std::cout << (*block[1]->As<ColumnUInt64>())[i] << " ";
                    std::cout << (*block[2]->As<ColumnString>())[i] << " ";
                    std::cout << (*block[4]->As<ColumnString>())[i] << " ";
                    std::cout << "\n";
                }
            }
        }
    );

    printf("display finished...\n");
}

int main()
{
    Client client(ClientOptions().SetHost("localhost").SetPassword("default"));
    create(client);
    display(client);
    return 0;
}

and when i execute it this is the result:

[cdev build]$ ./clicktest
create started...
create finished...
display started...
ROW count: 6
Segmentation fault (core dumped)
[davide@cdev build]$ ./clicktest
create started...
create finished...
display started...
terminate called after throwing an instance of 'clickhouse::UnimplementedError'
  what():  unsupported column type: 
Abort (core dumped)

the rows are correctly present into database as you can see here:

default=> drop table default.tbl_test;
SELECT 0
default=> select * from default.tbl_test;
 id | fno |     fname      |     ftype      
----+-----+----------------+----------------
  0 | 0   | field_name_0-0 | field_type_0-0
  0 | 1   | field_name_0-1 | field_type_0-1
  0 | 2   | field_name_0-2 | field_type_0-2
  1 | 0   | field_name_1-0 | field_type_1-0
  1 | 1   | field_name_1-1 | field_type_1-1
  1 | 2   | field_name_1-2 | field_type_1-2
(6 rows)

some one please can help me to understand what's wrong in my code? thank you

Enmk commented 1 year ago

Hi @gdcocchi ! Thank you for reporting, could you please provide the full stack trace of the exception (at least the part inside the clikhouse-cpp lib) and the line in your cord where it was thrown?

That would make reasoning about that issue much easier.

gdcocchi commented 1 year ago

below the stack trace:

[cdev build]$ ./clicktest 
create started...
create finished...
display started...
terminate called after throwing an instance of 'clickhouse::UnimplementedError'
  what():  unsupported column type: 
Abort (core dumped)

[cdev build]$ gdb clicktest core.989 
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/davide/develop/master_claw/master_claw/dev-test/clickhouse-test/build/clicktest...(no debugging symbols found)...done.
[New LWP 989]
Core was generated by `./clicktest'.
Program terminated with signal 6, Aborted.
#0  0x00007fafe5630387 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:55
55    return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
(gdb) where
#0  0x00007fafe5630387 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:55
#1  0x00007fafe5631a78 in __GI_abort () at abort.c:90
#2  0x00007fafe5f40a95 in __gnu_cxx::__verbose_terminate_handler () at ../../../../libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x00007fafe5f3ea06 in __cxxabiv1::__terminate (handler=<optimized out>) at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:38
#4  0x00007fafe5f3ea33 in std::terminate () at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:48
#5  0x00007fafe5f3ec53 in __cxxabiv1::__cxa_throw (obj=0x7fecf0, tinfo=0x485608 <typeinfo for clickhouse::UnimplementedError>, 
    dest=0x40bb60 <clickhouse::UnimplementedError::~UnimplementedError()>) at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:87
#6  0x0000000000427d03 in clickhouse::Client::Impl::ReadBlock(clickhouse::InputStream&, clickhouse::Block*) ()
#7  0x0000000000428196 in clickhouse::Client::Impl::ReceiveData() ()
#8  0x000000000042ab18 in clickhouse::Client::Execute(clickhouse::Query const&) ()
#9  0x000000000042b401 in clickhouse::Client::Select(std::string const&, std::function<void (clickhouse::Block const&)>) ()
#10 0x0000000000405fb2 in display(clickhouse::Client&) ()
#11 0x000000000040612d in main ()
(gdb) 
gdcocchi commented 1 year ago

I can add some other details. I tried to create the same table using only string fields, like this:

client.Execute("CREATE TABLE IF NOT EXISTS default.tbl_test (id String, fno String, fname String, ftype String) ENGINE = MergeTree PRIMARY KEY (id, fno, fname, ftype)");

and obiuvlsy changing the reading section like this:

void display(Client& client)
{
    printf("display started...\n");
    client.Select("SELECT id, fno, fname, ftype FROM default.tbl_test", [] (const Block& block)
   // client.Select("SELECT id, fno FROM default.tbl_test", [] (const Block& block)
        {
            if (block.GetRowCount() > 0)
            {
                std::cout << "ROW count: " << block.GetRowCount() << "\n";
                for (size_t i = 0; i < block.GetRowCount(); ++i)
                {
                    std::cout << (*block[0]->As<ColumnString>())[i] << " ";
                    std::cout << (*block[1]->As<ColumnString>())[i] << " ";
                    std::cout << (*block[2]->As<ColumnString>())[i] << " ";
                    std::cout << (*block[3]->As<ColumnString>())[i] << " ";
                    std::cout << "\n";
                }
            }
        }
    );

    printf("display finished...\n");
}

everithing is working fine:

[cdev build]$ ./clicktest
create started...
create finished...
display started...
ROW count: 6
0 0 field_name_0-0 field_type_0-0 
0 1 field_name_0-1 field_type_0-1 
0 2 field_name_0-2 field_type_0-2 
1 0 field_name_1-0 field_type_1-0 
1 1 field_name_1-1 field_type_1-1 
1 2 field_name_1-2 field_type_1-2 
display finished...

so apparentely, seems that mixing columns of different types, create some strange effect on client side library. I hope this info can be useful.

gdcocchi commented 1 year ago

adding some other detail. Surfing into library code, i found that probably there is some weird behavior into this code function

https://github.com/ClickHouse/clickhouse-cpp/blob/master/clickhouse/types/type_parser.cpp#L291

seems that the cached used to store columns definition was not working properly.

Enmk commented 1 year ago

What ClickHouse server version are you using? The initial example you provided (after fixing accessing columns out of range) works fine for me against 22.8.

gdcocchi commented 1 year ago

I'm using the server version 23.7.3 revision 54465 But in the meanwhile, I discovered that the issue is there when i switch to library version tag v2.4.0. Using the master branch, everithing is working fine.