Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support macros in sql queries #60

Open
andrey-mikhailov opened this issue Oct 18, 2021 · 1 comment
Open

Support macros in sql queries #60

andrey-mikhailov opened this issue Oct 18, 2021 · 1 comment

Comments

@andrey-mikhailov
Copy link

andrey-mikhailov commented Oct 18, 2021

ClickHouse macros are extremely useful when you're working on clustered environment. This library is great, but it doesn't support them.

Steps to reproduce:

  1. Configure clustered ClickHouse. I use 2 shards and 2 replicas.
  2. Run the code
import asyncio
from aiochclient import ChClient
from aiohttp import ClientSession

async def main():
    async with ClientSession() as s:
        client = ChClient(s)
        await client.execute("drop table if exists user_shard on cluster '{cluster}'")

if __name__ == '__main__':
    asyncio.run(main())

The string drop table if exists user_shard on cluster '{cluster}' is a valid sql code.

Expected behaviour:
no errors, user_shard table is created on all nodes.

Observed behaviour
There is an exception

Traceback (most recent call last):
  File "test.py", line 11, in <module>
    asyncio.run(main())
  File "/usr/local/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "test.py", line 8, in main
    await client.execute("drop table if exists user_shard on cluster '{cluster}'")
  File "venv/lib/python3.9/site-packages/aiochclient/client.py", line 233, in execute
    async for _ in self._execute(
  File "venv/lib/python3.9/site-packages/aiochclient/client.py", line 145, in _execute
    query = query.format(**query_params)
KeyError: 'cluster'

P.S.
The library automatically tries to replace variables in curly braces. I found the following code in client.py file

    async def _execute(
        self,
        query: str,
        *args,
        json: bool = False,
        query_params: Optional[Dict[str, Any]] = None,
        query_id: str = None,
        decode: bool = True,
    ) -> AsyncGenerator[Record, None]:
        query_params = self._prepare_query_params(query_params)
        query = query.format(**query_params)

Is it possible to add some parameter to execute method to make such transformation optionally? If I comment the string "query = query.format(**query_params)" the method will work fine.

As a temporary solution I use the following trick

import asyncio
from aiochclient import ChClient
from aiohttp import ClientSession


async def main():
    async with ClientSession() as s:
        client = ChClient(s)
        await client.execute("drop table if exists user_shard on cluster {cluster}",
                             params={"cluster": "{cluster}"})


if __name__ == '__main__':
    asyncio.run(main())

but it's not good because sql code is invalid. Creating Replicated* table is a more complicated case

CREATE TABLE IF NOT EXISTS user_ on cluster '{cluster}'
(
    userid       UInt64,
    emailaddress String,
)
 ENGINE = ReplicatedMergeTree('/clickhouse/{installation}/{cluster}/tables/{shard}/{database}/{table}', '{replica}')
@andrey-mikhailov
Copy link
Author

The another solution is to escape curly braces by double braces. This code works

import asyncio
from aiochclient import ChClient
from aiohttp import ClientSession


async def main():
    async with ClientSession() as s:
        client = ChClient(s)
        await client.execute("drop table if exists user_shard on cluster '{{cluster}}'")


if __name__ == '__main__':
    asyncio.run(main())

But in my real project I'm going to use Jinja templates for sql queries and double curly braces are reserved characters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant