-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
DBAL-968 - Rebuilt doModifyLimitQuery in SQLServerPlatform and fixed invalid test cases. #658
Conversation
Hello, thank you for creating this pull request. I have automatically opened an issue http://www.doctrine-project.org/jira/browse/DBAL-969 We use Jira to track the state of pull requests and the versions they got |
Hey @zeroedin-bill, did you base your PR on top of 2.4? Should be based on |
@Ocramius @zeroedin-bill don't bother... I'll make these aligned to master later today. |
@Ocramius i need to git better at git |
You'll git it right next time |
is it expected that this changes only tests (and breaking them) ? |
Yes - The tests that have been changed were missing FROM clauses in their subqueries, which is invalid. So I changed the test SQL to have a from clause. The tests now fail, revealing the fact that the behavior of the modifyLimitQuery func is not correct. |
@Ocramius i think i git it now... |
yeah, looks much better. now, if you have an idea to fix it, it will be great |
@stof, there are two issues related to TSQL that make the whole crazy thing necessary in the first place:
The $selectFromPattern regex was changed for some reason, and now it doesn't properly recognize the boundaries of the select list. I think the doModifyLimitQuery method in the SQLServerPlatform is kind of nuts. SQL Query parsing with regex is hard to get right. This IMO the best way to fix this method would be to rewrite it to do the following:
Return. It would be nice if everything could just pass an AST to the doModifyLimitQuery method, but that would require rewriting everything so that's a nope. It could instead be rewritten to accurately separate out the query parts using regex. It would need to do so without relying on finding specific strings that are passed by the ORM or other dependent libs. For example, SQLServerPlatform.php:1211 $isWrapped = (preg_match('/SELECT DISTINCT .* FROM \(.*\) dctrn_result/', $query)) ? true : false; This relies on finding a specific piece of SQL generated by the ORM. Coupling like this just makes this method worse and harder to debug. I'm not sure what the best course of action for fixing this method is. I think the tests cover all the use cases now at least. |
@zeroedin-bill I think we won't get this thing ever fixed in 2.x because of the lack of an AST to rebuild the query from. This method has been adjusted so many times now always fixing one issue and most probably introducing another. So I guess the only way for 2.x is to verify correct rebuilding of the query via regex through tests and always continuesly adding new tests for new (edge) cases. |
Fully agree with @deeky666 - regexes are annoying and will never be able to cover all use-cases. We'll have to patch in bugfixes as they come and then find a decent solution for 3.x, which has to be first of all specced out |
I rewrote doModifyLimitQuery -- still a WIP as it needs documentation. Works on all the test cases now. |
@zeroedin-bill decorators on an AST instead of having to parse the SQL ? which AST ? building the AST would require parsing the SQL into the AST first, which is platform-specific (as each platform can have its own specificities in their SQL, which is precisely why we have the Platform classes in DBAL) |
|
||
$isWrapped = (preg_match('/SELECT DISTINCT .* FROM \(.*\) dctrn_result/', $query)) ? true : false; | ||
// Strip order by out of the query | ||
$tsqlParts = $this->stripOrderByFromTsqlParts($tsqlParts); |
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.
what does TSQL
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.
TSQL is the SQL Server dialect of SQL
Please add some phpdoc for all your private methods to explain what they are about. Reviewing the code which does not have any comment and weird names (I don't understand what |
@stof I'll revise and add documentation and clean up. I'm off for today, but I'll be back on it tomorrow, thanks for the code review. |
@stof Revised... Let me know if you see any other issues and I'll fix em. |
/** | ||
* Breaks down a SQL statement into logical parts | ||
* | ||
* @param $sql |
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.
should be @param string $sql
@stof fixed |
15758bb
to
92d316e
Compare
@deeky666 @Ocramius I think this PR and #654 pretty much fix SQL server limiting and ordering. I've been running this code for a month and have had no issues. I could fix up #654 in a separate PR and add test cases for it if you'd like... As of now SQL Server platform is broken in master, and I'd like to see this get merged or another solution found before 2.5 gets released. |
As per discussion with @deeky666, I am not sure if we want to include this level of complexity just to fix MSSQL's syntax compatibility. I am really puzzled about this: on one side, I see amazing work, on the other side I see impossibility for us to maintain this or to keep it in maintainable shape. |
I just want limit queries to work right... Whatever solution achieves that and does not break on a regular basis is the right one in my opinion. As for this PR, I'm not married to my implementation, but the test cases are valid. I'm not sure a simple parser is any less maintainable in the long run than a chain of regexes. The history of the sql server doModifyLimitQuery implementation speaks to the difficulty of achieving a stable solution with regex alone. |
And hey, it was fun to write. |
@zeroedin-bill fully agree with that, I'm just really hesitant to merge here (mainly because the ball is on our side afterwards). |
@Ocramius Understandable... I can make a new PR with just the added/fixed tests tomorrow if you'd like... |
@zeroedin-bill I'd still want @deeky666's opinion here. |
@zeroedin-bill first of all I really appreciate your hard work on this. The only concerns I have about this PR is complexity and maintainability as @Ocramius pointed out. Your implementation is more or less a Parser for SQL Server |
…ries * Add test cases to AbstractSQLServerPlatformTestCase to cover queries issued by ORM paginator
92d316e
to
832acbd
Compare
@deeky666 A change I proposed to the ORM paginator in this PR would make a lot of the extra logic in this thing unnecessary -- If we can just assume that order by clauses inside subqueries are not valid and should be stripped out, then I think we can make this work without the parser stuff. |
Linking doctrine/orm#1220 |
Not needed due to a better solution. See #818 |
The recent change to SQLServerPlatform.php (17dad30) broke the ORM Paginator's queries on SQL server.
I investigated, and found that some of the test cases for the SQL Server platform weren't actually correct SQL. Also, there were no test cases that covered what the paginator is doing, so I've written test cases for those. I will open a pull request for this issue.
The modifyLimitQuery method in SQLServerPlatform.php should be fixed to pass the fixed old tests and the new tests.
My concern is that that method is becoming too complex, but that's an issue for another day.