You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importhttpx, asyncio, aiochclientc=aiochclient.ChClient(httpx.AsyncClient(), url="http://localhost:8123")
asyncdefmain():
# Errors responded by clickhouse in non-cluster mode are correctly forwarded as Exceptionstry:
res=awaitc.execute("CREATE TABLE x (a StupidType) ENGINE MergeTree()")
print(res)
exceptExceptionase:
print("THIS ERROR IS CORRECTLY FORWARDED: ", e)
# Errors in cluster mode are not raised, nor are they retrievable from the HTTP response... simply losttry:
res=awaitc.execute("CREATE TABLE x ON CLUSTER mycluster (a StupidType) ENGINE MergeTree()")
print(res) # Execute returns nothing, so you can't even retrieve the JSON-formatted error outputexceptExceptionase:
# We should get some exception...print("ERRORS FROM THE CLUSTER'S NODES ARE NOT FORWARDED, YOU'LL NEVER SEE THIS MESSAGE", e)
awaitc.close()
asyncio.run(main())
Why it happens
Clickhouse always responds with HTTP code 200, even if some node has failed to execute the statement. The error is embedded a JSON response like, e.g., :
{
"meta":
[
{
"name": "host",
"type": "String"
},
{
"name": "port",
"type": "UInt16"
},
{
"name": "status",
"type": "Int64"
},
{
"name": "error",
"type": "String"
},
{
"name": "num_hosts_remaining",
"type": "UInt64"
},
{
"name": "num_hosts_active",
"type": "UInt64"
}
],
"data":
[
["server101", 9000, "450", "Code: 450, e.displayText() = DB::Exception: TTL Expression GROUP BY key should be a prefix of primary key (version 21.3.20.1 (official build))", "5", "0"],
["server2", 9000, "450", "Code: 450, e.displayText() = DB::Exception: TTL Expression GROUP BY key should be a prefix of primary key (version 21.3.20.1 (official build))", "4", "0"],
["server103", 9000, "450", "Code: 450, e.displayText() = DB::Exception: TTL Expression GROUP BY key should be a prefix of primary key (version 21.3.20.1 (official build))", "3", "0"],
["server3", 9000, "450", "Code: 450, e.displayText() = DB::Exception: TTL Expression GROUP BY key should be a prefix of primary key (version 21.3.20.1 (official build))", "2", "0"],
["server102", 9000, "450", "Code: 450, e.displayText() = DB::Exception: TTL Expression GROUP BY key should be a prefix of primary key (version 21.3.20.1 (official build))", "1", "0"],
["server1", 9000, "450", "Code: 450, e.displayText() = DB::Exception: TTL Expression GROUP BY key should be a prefix of primary key (version 21.3.20.1 (official build))", "0", "0"]
We don't retrieve the HTTP response body for queries that went well (HTTP 200 code) in ChClient.execute => we don't have any access to those error messages embedded in the JSON response
we only exploit the HTTP response when we anticipate some records as a result. As CREATE TABLE and the like never return records, we simply drop the useful error messages when calling self._http_client.post_no_return(...).
Solution
Would you accept a PR that won't drop HTTP response body and when body embeds some error messages wrap the messages into some raised exception at ChClient._execute level ?
Is there any bad side effect to do this ?
The text was updated successfully, but these errors were encountered:
How to reproduce
Why it happens
ChClient.execute
=> we don't have any access to those error messages embedded in the JSON responseIncriminated code
https://github.com/maximdanilchenko/aiochclient/blob/master/aiochclient/client.py#L189
we only exploit the HTTP response when we anticipate some records as a result. As
CREATE TABLE
and the like never return records, we simply drop the useful error messages when callingself._http_client.post_no_return(...)
.Solution
Would you accept a PR that won't drop HTTP response body and when body embeds some error messages wrap the messages into some raised exception at
ChClient._execute
level ?Is there any bad side effect to do this ?
The text was updated successfully, but these errors were encountered: