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

support for cross joins. don't error on joins of subqueries #569

Merged
merged 8 commits into from
Mar 16, 2023
Merged

support for cross joins. don't error on joins of subqueries #569

merged 8 commits into from
Mar 16, 2023

Conversation

jakubvojacek
Copy link
Contributor

@jakubvojacek jakubvojacek commented Mar 15, 2023

  • support for multiple joins, up to now it was OK just for single join, this adds support for multiple
  • skips AST for
    • cross joins
    • queries with subqueries
    • when condition is null (previous it was throwing runtime exception, now it just screams in debug)

The changes works fine for my codebase

@staabm
Copy link
Owner

staabm commented Mar 15, 2023

changes look good to me, but require test-cases which fail without the actual code changes

@jakubvojacek
Copy link
Contributor Author

changes look good to me, but require test-cases which fail without the actual code changes

yea, I will try to add some

@@ -365,4 +365,18 @@ public function joinSelectOutsideCondition(PDO $pdo): void
assertType('PDOStatement<array{adaid: int<-32768, 32767>, 0: int<-32768, 32767>, eadavk: numeric-string|null, 1: numeric-string|null}>', $stmt);
}

public function multipleJoins(PDO $pdo): void
{
$stmt = $pdo->query('SELECT adaid from ada join ak on adaid = eladaid inner join typemix on adaid = c_int');
Copy link
Owner

@staabm staabm Mar 15, 2023

Choose a reason for hiding this comment

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

Please also select columns from within the join condition, make sure these are narrowed properly and make sure columns from joined tables not part of the condition are also narrowed properly.

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 tried, please check, is that you you had in mind?

Comment on lines 76 to 90
if ($from->getRight() instanceof TableReferenceSubquery || $from->getLeft() instanceof TableReferenceSubquery) {
if (QueryReflection::getRuntimeConfiguration()->isDebugEnabled()) {
throw new UnresolvableQueryMixedTypeException('Cannot narrow down types for SQLs with subqueries: ' . $queryString);
}

return $resultType;
}

if ($from instanceof InnerJoin && $from->isCrossJoin()) {
if (QueryReflection::getRuntimeConfiguration()->isDebugEnabled()) {
throw new UnresolvableQueryMixedTypeException('Cannot narrow down types for cross joins: ' . $queryString);
}

return $resultType;
}
Copy link
Owner

Choose a reason for hiding this comment

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

why do we need these early returns?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it cannot collect proper data about joins and the columns hence it gives up on narrowing down the type

Copy link
Owner

@staabm staabm Mar 16, 2023

Choose a reason for hiding this comment

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

but would it make a difference for the added test-cases if we just drop it here. wouldn't it give up after the loop then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

without the early return, it wouldnt work, the tests would fail

1) Error
The data provider specified for staabm\PHPStanDba\Tests\DbaInferenceTest::testFileAsserts is invalid.
Error: Call to undefined method SqlFtw\Sql\Dml\TableReference\TableReferenceSubquery::getTable()
/Users/jakubvojacek/Sites/phpstan-dba/src/SqlAst/ParserInference.php:96
/Users/jakubvojacek/Sites/phpstan-dba/src/QueryReflection/QueryReflection.php:135
/Users/jakubvojacek/Sites/phpstan-dba/src/PdoReflection/PdoStatementReflection.php:88
/Users/jakubvojacek/Sites/phpstan-dba/src/Extensions/PdoQueryDynamicReturnTypeExtension.php:106

Copy link
Owner

Choose a reason for hiding this comment

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

ahh I see.

lets keep it then, but add a new exception type to use instead of UnresolvableQueryMixedTypeException here.
the tip for the exception should make the user aware that he triggered a case not yet supported and that it would be awesome if a repro can be reported to our issue tracker

Copy link
Contributor Author

Choose a reason for hiding this comment

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

but that will trigger phpstan internal error and the analysis will fail and phpstan cache wont be saved,right?I originally had the exception there but it was so annoying when running on my codebase that I decided to hide it behind debug flag.

Copy link
Owner

Choose a reason for hiding this comment

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

I think it should work when we create a new subclass of UnresolvableQueryException

similar to how we did with https://github.com/staabm/phpstan-dba/blob/main/src/UnresolvableQueryMixedTypeException.php which seems to work for you atm

Copy link
Owner

Choose a reason for hiding this comment

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

e.g. UnresolvableAstInQueryException

Copy link
Contributor Author

Choose a reason for hiding this comment

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

so you want me to rename UnresolvableQueryMixedTypeException to UnresolvableAstInQueryException on those three places that it thrown in ParserInference right?

I checked where UnresolvableQueryMixedTypeException was used and its only on one place and its after the QueryReflection::getRuntimeConfiguration()->isDebugEnabled() condition as well

Copy link
Owner

@staabm staabm Mar 16, 2023

Choose a reason for hiding this comment

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

nope, I want you to create a new exception class and use it here in this few places of this PR, but leave UnresolvableQueryMixedTypeException as is across the codebase

UnresolvableQueryMixedTypeException signals that a query cannot be resolved - meaning we are not able to figure out the query string at all.
in our scenario here, we already know the query string but are not (yet?) able to analyse it with AST properly (since we did not yet implement everything you can express with sql)


public function ignoredAstQueries(PDO $pdo): void
{
$pdo->query('SELECT adaid from ada inner join (select akid from ak) on akid = adaid');
Copy link
Owner

@staabm staabm Mar 16, 2023

Choose a reason for hiding this comment

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

we are missing a assertion for this line

Copy link
Contributor Author

Choose a reason for hiding this comment

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

because it has a different output for pdo-mysql and mysqli reflectors (but that is unrelated to AST analysis since we give up on that due to the subquery)

Copy link
Owner

Choose a reason for hiding this comment

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

without an assertion this line does not have value. what is the difference between the reflectors regarding this statement?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

my bad, must have been doing something wrong back then when i was testing. I just pushed a new assertion, hopefully CI will be green

Copy link
Owner

@staabm staabm left a comment

Choose a reason for hiding this comment

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

thank you

@staabm staabm changed the title AST improvements support for cross joins. don't error on joins of subqueries Mar 16, 2023
@staabm staabm enabled auto-merge (squash) March 16, 2023 08:30
@staabm staabm added this to the SQL AST milestone Mar 16, 2023
@staabm staabm merged commit 0d7b290 into staabm:main Mar 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants