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

fix: COUNT() being casted as string #7641

Closed
wants to merge 8 commits into from
Closed

fix: COUNT() being casted as string #7641

wants to merge 8 commits into from

Conversation

Grafikart
Copy link
Contributor

Some functions have a predefined type and could be resolved correctly by the SQLWalker. I don't want to change things too much but it could be possible to do the same thing for other functions like SUM for instance that would be resolved to float.

A much better solution would be to retrieve the aggregateExpression, then the pathExpression to resolve the type from the field but it's not feasable without an accessor from FunctionNode class.

@Grafikart
Copy link
Contributor Author

Grafikart commented Mar 7, 2019

A much better solution (but I need to know if it would be accepted before implementing it) would be to add an interface Typeable on the FunctionNode class that would define a getReturnType(): string

This function would return "string" on the FunctionNode class but could return something else on the child class CountFunction, SumFunction or else.

Then checking for this interface would be sufficient to resolve the type and every function could inform the walker of the type returned.

Copy link
Member

@Ocramius Ocramius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a decent idea, but needs tests to back it.

Also, I'd say that we need a private method that identifies the type for built-in function nodes.

@Grafikart
Copy link
Contributor Author

I can try to write test but the SqlWalkerTest seems a bit empty ^^
You want me to try the interface way ?

@Ocramius
Copy link
Member

Ocramius commented Mar 7, 2019

I suggest looking at integration tests that verify the generated ResultSetMapping instance from a full parser run.

@Grafikart
Copy link
Contributor Author

Good idea, can you point me to the file where I should add this test ?

@Ocramius
Copy link
Member

Ocramius commented Mar 7, 2019

Possibly need a new file, similar to https://github.com/doctrine/orm/blob/master/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php, but focused on resultset mapping

@Grafikart
Copy link
Contributor Author

I added the tests and altered more functions

Copy link

@flohw flohw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙂

tests/Doctrine/Tests/ORM/Query/SelectSqlMappingTest.php Outdated Show resolved Hide resolved
tests/Doctrine/Tests/Models/CMS/CmsProduct.php Outdated Show resolved Hide resolved
lib/Doctrine/ORM/Query/AST/TypableNode.php Outdated Show resolved Hide resolved
lib/Doctrine/ORM/Query/AST/TypableNode.php Outdated Show resolved Hide resolved
tests/Doctrine/Tests/ORM/Query/SelectSqlMappingTest.php Outdated Show resolved Hide resolved
@Grafikart
Copy link
Contributor Author

Everything should be fixed now


/**
* @inheritDoc
*/
Copy link
Member

@greg0ire greg0ire Mar 30, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no doc to inherit yet, is this in case some is added in the future?

@@ -1388,7 +1388,12 @@ public function walkSelectExpression($selectExpression)
if (! $hidden) {
// Conceptually we could resolve field type here by traverse through AST to retrieve field type,
// but this is not a feasible solution; assume 'string'.
$this->rsm->addScalarResult($columnAlias, $resultAlias, Type::getType('string'));
if ($expr instanceof Query\AST\TypedExpression) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the comment above is no longer 100% accurate? Should probably be "assume 'string' when the expression is not typed"?

Copy link
Member

@greg0ire greg0ire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please squash your commits together and make the commit message more accurate, this is no longer just about COUNT().


use Doctrine\DBAL\Types\Type;

interface TypedExpression
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this interface for internal use only? If yes, please mark it as such with @internal + a comment. If not, please document it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so it can be used by custom function created by the user (for instance COS() could implement this interface)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, then maybe document it?

@greg0ire
Copy link
Member

greg0ire commented Dec 1, 2019

@Grafikart why did you delete your repository? I hope I didn't discourage you with my nitpicks?

@greg0ire greg0ire self-assigned this Dec 1, 2019
Copy link
Member

@ostrolucky ostrolucky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a nice, simple patch solving the problem, however I'm not sure we should bite the bullet with floats. COUNT() and LENGTH() as integer types are fine, but casting to float in PHP will mean losing accuracy. It's also quite strange to make eg. ABS(1) return 1.0. Also, this a BC break and as such should be documented.


public function getReturnType() : Type
{
return Type::getType(Type::STRING);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why defining this when it's default fallback anyway?

Copy link
Member

@ostrolucky ostrolucky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a nice, simple patch solving the problem, however I'm not sure we should bite the bullet with floats. COUNT() and LENGTH() as integer types are fine, but casting to float in PHP will mean losing accuracy. It's also quite strange to make eg. ABS(1) return 1.0. Also, this a BC break and as such should be documented.

@Grafikart
Copy link
Contributor Author

@greg0ire I wanted to clean my repositories and I ended up deleting all my forks with an automated tool :D. I have no problem with the nitpicking since it makes the code better for everyone and helps me learning how to be more rigorous.

To be honest I forgot about this PR but I could send a new PR with the same fixes if you still want this functionnality.

@ostrolucky
Copy link
Member

Please do so. I think there is an interest from core team to have this functionality in some way

@Grafikart
Copy link
Contributor Author

I did a new PR #7941. I'm closing this one since I deleted the fork by mistake 👎

@Grafikart Grafikart closed this Dec 1, 2019
@greg0ire greg0ire removed this from the 3.0.0 milestone Jun 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants