-
Notifications
You must be signed in to change notification settings - Fork 144
Support for expressions #101
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
Conversation
src/Query/Expression.php
Outdated
/** | ||
* @var string | ||
*/ | ||
protected $expression = ''; |
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.
IMO there should not be a default value and not be protected. Let there only be a constructor as the way to create a valid object.
protected $expression = ''; | |
private $expression; |
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.
Done. Sorry, just now understood that this change could be applied right in github.
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.
Np, new feature introduced yesterday ;)
src/Query/Expression.php
Outdated
namespace ClickHouseDB\Query; | ||
|
||
/** | ||
* Query expression |
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.
This would deserve more explanation
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.
Updated docblock with example and param type.
src/Query/Expression.php
Outdated
/** | ||
* Query expression | ||
* | ||
* @package ClickHouseDB |
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.
This comment can be removed
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.
Removed.
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.
Personally I like the idea 👍
Can we cover it with integration test so we make sure it doesn't get broken in the future? I suggest to place it into new ClickHouseDB\Tests\Query\ExpressionTest
Travis Code Style build is currently broken (will be fixed when #100 is merged) so it can be ignored Scrutinizer however found some issues, mostly the code style https://scrutinizer-ci.com/g/smi2/phpClickHouse/inspections/e96a39a6-5929-44aa-ae63-943b77da290d/issues/ |
Scrutinizer is now ok. I'll remove method |
Everything that is public = API. And even though you create another method that instantiates it, it will still be perfectly valid to instantiate it on it's own. If you want to encapsulate it, you can create something like expression builder (example https://www.doctrine-project.org/projects/doctrine-collections/en/latest/expression-builder.html). |
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.
And what do you think about the test 🤔 (#101 (review))?
Tests are a must. Just wanted to finalize how it will be used first. Regarding ExpressionBuilder - most probably I will not be able to do it in any close future :) |
In older version there was no call
But both options doesn't look good to me. |
Commit that introduced
But it doesn't gives any idea why type conversion was added. W/o knowing reasons for that I cannot offer a good solution. |
Yup, that cleaned up value formatting code that was spread across several classes into one You can replicate this part for Expression and should be good 5f4fe72#diff-8b1652bb2da78b48114bdfa44b1f9b3fR35 |
Not sure I understood correctly. You mean make it this way? if ($value instanceof Expression) { |
Exactly. And maybe remove |
Main reasoning for class wrapper ( if (is_string($value) && $encode) { If replace if ($value instanceof Expression) {
return $value->getValue();
} check I noted before will not be bypassed. |
This is what I can offer for now, but I don't like this solution, to be honest. |
What in particular you don't like about it? |
class Expression | ||
{ | ||
/** @var string */ | ||
private $expression; |
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.
One more thing is on my mind. This Expression you introduced could easily replace my Type I introduced here #94.
If $expression
would be of type mixed
and we dropped __toString()
and replaced with something like getValue()
(@return mixed
) I could then drop those classes of mine in next PR.
My intention was to use it like this
UInt64::fromString('18446744073709551615')
but now it could be replaced with
new Expression('18446744073709551615')
for lower numbers eg. new Expression(1844674)
My main point is, why to limit the expression only for strings?
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.
There was different intention and reasoning for Type
and Expression
.
Expression
was made to bypass quoting. Inspired by other DB-related libs. But, btw, not necessarily in a best way to implement this intention. I just found it less obtrusive and easier to merge back to my fork in future.
Type
, as I can see, introduced for different reason - to allow safely and in a controlled fashion add new, potentially complex types(what about Date
type, f.ex.?).
While Expression
seems to be universal here I'm against replacing Type
with Expression
, because Expression
is a last resort. Unsafe one, I must say. Should be used only when there are no other options. In theory, with time, Expression
could be replaced with some support for functions from library itself. Like
new Function\UUIDStringToNum($uuid)
instead of
new Expression("UUIDStringToNum('0f372656-6a5b-4727-a4c4-f6357775d926')")
.
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.
kk, let's just leave it like it is
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.
So, maybe, Expression
could become either a higher level (abstract?) class or even Interface and Type
can be a descendant to it. Because you're right in one aspect - Expression
could solve a wider range of requirements including ones that are solved by Type
.
But it will require to refactor this part in src/Quote/StrictQuoteLine.php
:
$value = ValueFormatter::formatValue($value, false);
if (is_float($value) || is_int($value)) {
return (string) $value;
}
if (is_string($value) && $encode) {
if you want Expression::getValue()
to return string. Because otherwise string
"UUIDStringToNum('0f372656-6a5b-4727-a4c4-f6357775d926')"
will become
'\'UUIDStringToNum(\\\'0f372656-6a5b-4727-a4c4-f6357775d926\\\')\''
after quoting.
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.
You're right it might need some tweak in that part of code. But see this line
https://github.com/smi2/phpClickHouse/blob/master/src/Quote/StrictQuoteLine.php#L74
If replaced by if ($value instanceof Expression) {
it might do the trick.
BTW I'd definitely be for interface Expression
rather than abstract class Expression
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.
Yes, missed that one. So it should be something like this IMO:
if ($value instanceof NumericType) {
$encode = $value->doQuoting();
}
But in this case abstract class AND interface required. Abstract is required to define default doQuoting() : boolean
. I think I can do it after this one is merged. Because, obviously, it will be refactoring of Type
and Expression
.
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.
Yes. I'd name it something like needsEncoding() : bool
and abstract class is IMO not required, we don't really need default value so interface will do. But for sure in next PR :)
Cannot say. It just smells bad for me. Something is wrong here. But it's working, so I'm not freaking out :) |
I suppose some interface will emerge soon for that case. Type and Expression could have shared one. |
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.
LGTM 🚢
WDYT @isublimity?
Merge to master |
How it's used in our project(simplified):
Where simplified
sometable
is: