trinodb / trino-python-client

Python client for Trino
Apache License 2.0
328 stars 163 forks source link

Escape url parameters in sqlalchemy connection strings #235

Closed mdesmet closed 2 years ago

mdesmet commented 2 years ago

Currently it is not possible to create a Trino url in sqlalchemy urls containing characters like &, ' ' or @. The values should be properly encoded and decoded.

This PR provides a helper method that properly encodes the passed values and ensures that values are properly decoded before passing down as dbapi.connect parameters.

>>> URL(
...                         user="user@test.org/my_role",
...                         password="pass /*&",
...                         host="localhost",
...                         session_properties={"query_max_run_time": "1d"},
...                         http_headers={"trino": 1},
...                         extra_credential=[
...                             ("user1@test.org/my_role", "user2@test.org/my_role"),
...                             ("user3@test.org/my_role", "user36@test.org/my_role")],
...                         experimental_python_types=True,
...                         client_tags=["1 @& /\"", "sql"],
...                     )
'trino://user%40test.org%2Fmy_role:pass %2F*&@localhost:8080?source=trino-sqlalchemy&session_properties=%7B%22query_max_run_time%22%3A+%221d%22%7D&http_headers=%7B%22trino%22%3A+1%7D&extra_credential=%5B%28%27user1%40test.org%2Fmy_role%27%2C+%27user2%40test.org%2Fmy_role%27%29%2C+%28%27user3%40test.org%2Fmy_role%27%2C+%27user36%40test.org%2Fmy_role%27%29%5D&client_tags=%5B%221+%40%26+%2F%5C%22%22%2C+%22sql%22%5D&experimental_python_types=true'

Release notes

( ) This is not user-visible and no release notes are required. ( ) Release notes are required, please propose a release note for me. (x) Release notes are required, with the following suggested text:

* Support sqlalchemy url generation through `trino.sqlalchemy.URL` helper method
mdesmet commented 2 years ago

@hovaesco: PTAL

mdesmet commented 2 years ago

@hashhar, @ebyhr : Please have a look. This is important for Galaxy users to be able to use sqlalchemy.

mdesmet commented 2 years ago

@hashhar : PTAL

mdesmet commented 2 years ago

@hashhar : PTAL. I have not added another class as it is a simple one liner using the typical json.loads recipe but looping through it and instantiating a tuple based on the array.

kwargs["extra_credential"] = [
    tuple(extra_credential) for extra_credential in json.loads(unquote_plus(url.query["extra_credential"]))
]