-
Notifications
You must be signed in to change notification settings - Fork 302
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
⭐ Improve parameterized query support - fixes #793 #794
Conversation
pypika/terms.py
Outdated
@property | ||
def placeholder(self): | ||
if callable(self._placeholder): | ||
return self._placeholder(None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how does this work on None?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! Will take a deeper look later |
@wd60622 Do you think you'll have time this week? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really good.
Just some comments on type hints, raising errors, and combining logic
def named_placeholder_gen(idx: int) -> str: | ||
return f'param{idx + 1}' | ||
|
||
|
||
class Parameter(Term): | ||
is_aggregate = None | ||
|
||
def __init__(self, placeholder: Union[str, int]) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type hint here doesn't include callable? Is that correct still?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, only ListParameter and DictParameter (and classes that inherit from them) support callable.
The base parameter does not.
class Parameter(Term): | ||
is_aggregate = None | ||
|
||
def __init__(self, placeholder: Union[str, int]) -> None: | ||
super().__init__() | ||
self.placeholder = placeholder | ||
self._placeholder = placeholder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be good to use a setter here. With that, implementing a check for the correct type can happen on initialization if put in the setter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I follow how to do this pythonically? Could you share some pseudo code to show what you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mvanderlee I believe @wd60622 was referring to the following:
@property
def placeholder(self):
return self._placeholder
@placeholder.setter
def placeholder(self, placeholder):
# can add checks here if needed
self._placeholder = placeholder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, which adds no value and isn't pythonic. This isn't Java/C#.
It would also break parameters. After a parameter has been created and used, any changes to the placeholder will break queries. Which is why I've made it private with a getter only.
I haven't changed the type, so any type checks would have to be part of a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would disagree with you on it not being Pythonic, as it’s a native language feature.
Also, I was trying to be helpful, but given your receptiveness to discussion and tone, I won’t proceed.
Good luck.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for my tone @danielenricocahall it'd been a rough week and I lashed out.
As for pythonic. This video does a good job at explaining language feature vs pythonic.
Raymond Hettinger - Beyond PEP 8 -- Best practices for beautiful intelligible code - https://www.youtube.com/watch?v=wf-BqAjZb8M
Do you have any thoughts as well? @AzisK |
Could we also have this functionality described in pypika docs? |
The tests look really nice. What about adding |
I just wanted to say that I'm going to fork your branch because this feature is really useful, and I'm using it in my own project to help me build a custom high level query language: https://github.com/reasv/panoptikon/blob/master/src/panoptikon/db/pql/build_query.py I'm resorting to making my own fork of PyPika and merging a bunch of these PRs because it doesn't seem PyPika is getting much merged lately and there are open bugs that otherwise block development: d7a4054 |
Any progress on getting this merged? :) |
Hello, I asked @mvanderlee for a test for |
I forked @mvanderlee 's fork and added a test for PyformatParameter: Commit |
@larsschwegmann could you make a PR? Is it better for me to push this change to this commit? Probably |
If it's possible, I guess it would be best if you could just add the commit to this PR, just for the sake of documentation. Then you'll still have all the discussion in the PR that was merged 😄 |
Thank you @larsschwegmann I've added it to the branch! |
I could merge but linting fails. It's not a big deal but it would be good to lint before. Also unit tests for other Python versions fail but it's probably a bug of Github actions which is super annoying. It seems that they fail due to a race condition |
@AzisK I'll run the linter, but it's an issue in the master branch. The linter is failing on lines that were not altered by this PR. I see the same errors with other PRs. |
2ae30df
to
9ba1241
Compare
The affected code wasn't in this fork yet, so I rebased in order to fix it. |
All seems good, I can merge it. Thanks for the work |
Fixes #793
The implemented tests speak for themselves, but here is an extract:
This would allow the user to easily plug into SQLAlchemy for example: