-
Notifications
You must be signed in to change notification settings - Fork 7.9k
fix bug 81343: inconsistent type conversion after closeCursor #7355
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
S->cols is already freed in the statement destructor and since caa7100 the column data is only populated on the first execute() which means that on subsequent execute()s after closeCursor was called, all meta-data for column types was removed and never restored
as I said on the bug report, I would love to get @nikic's 👀 on this one as he did the big PDO result refactoring and as I'm not 100% sure it's safe to not free the column information on The other approach would be to restore the freeing of the column metadata and call |
Don't we need to |
I don't know. It wasn't happening prior to caa7100 either. I just checked PHP-8.0 HEAD |
Does pgsql have any notion of multiple result sets (where each result set might have different columns)? |
AppVeyor fails with:
I haven't seen this kind of message before ... where does it come from? |
it's hard-coded in ext/pdo_pgsql/tests/bug69752.phpt, but I think the test is not quite correct: yes, the metadata persists after closeCursor, but it's not growing unbounded (increasing the iteration count in the test does not cause the "leak" to grow) With regards to result sets: Postgres gained that feature with Postgres 11 recently, but I don't think PDO had or has any way for accessing these. |
never mind. it is - something is not being freed. I missed the I guess we need to continue to free the column info but instead use |
however, I don't understand where the leak detected by the test is coming from. As far as I can see, memory for php-src/ext/pdo_pgsql/pgsql_statement.c Lines 243 to 246 in a4e2068
anyways - I'll find out. Calling describe on each execute would need to be done through the PDO extension itself which might come at a considerable performance cost for other database drivers. |
aha! this also checks for I'm off for family duties now, but I'll have a correct fix tomorrow Central Europe summer time without describing again. Sorry for the confusion. |
now that the describer is only called for the initial execution, the column metadata needs to stay around even after closeCursor is called (which resets stmt->executed back to 0) This is not correct in light of multiple result sets, but the PDO postgres driver does not provide any support for those
I have added an additional commit that does the Doing this correctly even with multiple rowsets would require a bit of a rework, but that's probably true for the rest of the driver anyways. On my machine all ext/pdo_pgsql tests now pass. |
It would be good to check how pgsql behaves when you modify the table schema between two executes. This used to crash with MySQL: https://github.com/php/php-src/blob/master/ext/pdo_mysql/tests/change_column_count.phpt I suspect that the way this is currently done in the pgsql driver could also result in a crash... |
very good idea. I'll check and I'm quite sure that in the best case it will behave like the bug 81343 and return newly added values as strings and in the worst case, it will crash. Looking at the PDO framework itself, I think I can make the Postgres driver ask the framework to call |
good news: Postgres thought of this and will throw an error if the schema has changed behind a prepared statement's back:
however, with Given the correct handling in case of native prepares and given the unchanged behavior of emulated prepares, I think the current implementation of the PR is fine |
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 think the whole "describe" functionality in PDO probably needs a redesign, but let's go with this for now to address the immediate problem...
@nikic Why does the commit show up as unverified? |
That’s because I told GitHub that my commits are signed but this was of course rebased and committed by @nikic but authored by me. I will update my GitHub config. |
S->cols
is already freed in the statement destructor and since caa7100 the column data is only populated on the firstexecute()
which means that on subsequent execute()s aftercloseCursor
was called, all meta-data for column types was removed and never restored, so any possible data type conversion was not happening any more.