Fix params substitution for select queries#141
Conversation
|
oh, probably a duplicate of #138... in any case I really need this logic 😢 |
|
@dmkulazhenko , hello. LGTM, tests passed, mypy is OK with these files.
|
|
@stankudrow, changelog entry and test for |
|
@misuzu, please, proceed with the PR |
|
@dmkulazhenko , hello. Any updates about the suggestions above? |
|
@dmkulazhenko , hello. Are you willing to finish this PR including the suggestions above? |
@stankudrow, maybe I get it wrong, but what should I do?
upd: seems to be you expect that I will drop |
|
@stankudrow, re-review pls |
@dmkulazhenko , done. @DaniilAnichin , could you also have a look, please? Looks good to me, that last time I ran mypy over these files the checker wasn't unpleased. |
DaniilAnichin
left a comment
There was a problem hiding this comment.
Looks good, no comments
|
@long2ice , hello. The PR is ready to be merged IMO. |
|
This release might want a warning/heads up for those upgrading, as this breaks existing code that already uses the |
Hello. Could you possibly list here a small example that demonstrates your point? Also, please do feel free to open a PR (if you like) that 1) does not decline the changes (to a certain extent) from this PR and 2) allows to handle the case you have mentioned before so the compatibility wouldn't break. It is possible to mitigate risks while this work isn't really released. |
The simplest example I have would be a query like this: await self.cursor.execute(
"""
SELECT
EXISTS(
SELECT 1
FROM table_a
WHERE profile_id = %(profile_id)s
) AS a_enabled,
EXISTS(
SELECT 1
FROM table_b
WHERE profile_id = %(profile_id)s
) AS b_enabled
""",
{"profile_id": profile_id}
)
Another parameter for setting this came to mind, but imagine that would be pretty clunky. The other alternative was this, but unsure of this possibly having gotchas down the line. @staticmethod
def substitute_params(query: str, params: Mapping[str, Any]) -> str:
if not isinstance(params, Mapping):
raise ValueError("Parameters are expected to be a mapping")
first_param = next(iter(params))
if f"{{{first_param}}}" in query:
return query.format(**escape_params(params))
else:
return query % escape_params(params) |
Hm, what to try, e.g., this solution? And the snippet may be like this: @baconfield , would you like to open a PR and try this or any better solution or should I do this? Also, consider updating tests on:
|
Yeah that looks like a better approach, I don't mind making a PR, it will just be a bit as I'll need to wait until after hours tonight. |
|
@stankudrow @baconfield , tbh it's totally my fault... I feel really stupid right now, because I had no idea that old python format style have an ability to pass arguments ( So, the whole idea of this PR is pointless... My initial problem was just lack of knowledge of old-style python formatting 😢. I believe @barakor had same intentions in #138. There is 3 options to do now:
If with 1st and 2nd options implementation is clear, 3rd option will require changes not only in clickhouse-sqlalchemy, but also in sqlalchemy:
As you can see there is no option like To mitigate such PRs in future it's a good idea to add section with an example of parametrized query or a link to https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting. Btw, finding this documentations by googling something like "python named percent formatting" is not that easy, thanks to dummy guides copy-pasters 🙃. |


Select queries use substitution of arguments using
%formatting, which doesn't work as far asargspassed asMapping.This PR changes substitution formatting mechanism to
str.formatmethod.