long2ice / asynch

An asyncio ClickHouse Python Driver with native (TCP) interface support.

Home Page:https://github.com/long2ice/asynch

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Connection hangs up

knucklesuganda opened this issue · comments

I have a Python program with asynch library. I insert the data that I cannot validate beforehand, and because of that, we can insert UInt64 data into UInt32 field and that returns

Code: 53. Type mismatch in VALUES section. Repeat query with types_check=True for detailed info. Column ie: argument out of range

I handle that error and try to insert the data once again, but Clickhouse hangs up the connection with a new error: Code: 33. DB::Exception: Cannot read all data in NativeBlockInputStream.

Release: v21.9.4.35-stable
Environment: Docker

How to reproduce

  • Clickhouse version: version 21.9.4 revision 54449
  • Python 3.8 with asynch library
  • CREATE TABLE IF NOT EXISTS test(data UInt32) ENGINE = MergeTree() ORDER BY(data) PRIMARY KEY (data) PARTITION BY (data)
  • [(429496729500,)] + [(x,) for x in range(100)]
  • INSERT INTO test(data) VALUES

Expected behavior

Successful insertion after invalid data removal

Error message and/or stacktrace

>> <Error> TCPHandler: Code: 33. DB::Exception: Cannot read all data in NativeBlockInputStream. Rows read: 0. Rows expected: 100. (CANNOT_READ_ALL_DATA), Stack trace (when copying this message, always include the lines below):
> 
> 0. DB::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, bool) @ 0x936a17a in /usr/bin/clickhouse
> 1. DB::NativeBlockInputStream::readData(DB::IDataType const&, COW<DB::IColumn>::immutable_ptr<DB::IColumn>&, DB::ReadBuffer&, unsigned long, double) @ 0x10d49083 in /usr/bin/clickhouse
> 2. DB::NativeBlockInputStream::readImpl() @ 0x10d49ca2 in /usr/bin/clickhouse
> 3. DB::IBlockInputStream::read() @ 0x104c3a86 in /usr/bin/clickhouse
> 4. DB::TCPHandler::receiveData(bool) @ 0x117b6ee2 in /usr/bin/clickhouse
> 5. DB::TCPHandler::receivePacket() @ 0x117ac3ab in /usr/bin/clickhouse
> 6. DB::TCPHandler::readDataNext() @ 0x117ae56f in /usr/bin/clickhouse
> 7. DB::TCPHandler::processInsertQuery() @ 0x117ac908 in /usr/bin/clickhouse
> 8. DB::TCPHandler::runImpl() @ 0x117a5dff in /usr/bin/clickhouse
> 9. DB::TCPHandler::run() @ 0x117b8519 in /usr/bin/clickhouse
> 10. Poco::Net::TCPServerConnection::start() @ 0x1437788f in /usr/bin/clickhouse
> 11. Poco::Net::TCPServerDispatcher::run() @ 0x1437931a in /usr/bin/clickhouse
> 12. Poco::PooledThread::run() @ 0x144ac199 in /usr/bin/clickhouse
> 13. Poco::ThreadImpl::runnableEntry(void*) @ 0x144a842a in /usr/bin/clickhouse
> 14. start_thread @ 0x9609 in /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
> 15. clone @ 0x122293 in /usr/lib/x86_64-linux-gnu/libc-2.31.so``

Additional context

Here is the code that you can use to reproduce that error:

import asyncio

from asynch.errors import TypeMismatchError
from asynch import create_pool


async def execute_query(connection_pool, query, values=None):
    async with connection_pool.acquire() as connection:
        async with connection.cursor() as cursor:
            if values is not None:
                await cursor.execute(query, values)
            else:
                await cursor.execute(query)


async def main():
    connection_pool = await create_pool(
        host='127.0.0.1',
        port='9000',
        database='default',
        user='default',
        password='',
        maxsize=30,
    )

    await execute_query(
        connection_pool=connection_pool,
        query="""
        CREATE TABLE IF NOT EXISTS test(data UInt32) ENGINE = MergeTree()
        ORDER BY(data) PRIMARY KEY (data) PARTITION BY (data)
        """,
    )

    invalid_values = [(429496729500,)] + [(x,) for x in range(100)]

    try:
        await execute_query(
            connection_pool=connection_pool,
            query="INSERT INTO test(data) VALUES",
            values=invalid_values,
        )
    except TypeMismatchError as exc:
        print(exc)
        del invalid_values[0]
        await execute_query(
            connection_pool=connection_pool,
            query="INSERT INTO test(data) VALUES",
            values=invalid_values,
        )


if __name__ == '__main__':
    event_loop = asyncio.get_event_loop()
    event_loop.create_task(main())
    event_loop.run_forever()