Skip to content

Conversation

@NathanFreeman
Copy link
Contributor

https://bugs.php.net/bug.php?id=78227

I am not sure whether it could solve this bug.

If not, your suggestions would be greatly appreciated.

Thanks.

Copy link
Member

@cmb69 cmb69 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 for working on this! I will have a closer look soon, but you can address my comments right away, if you like.

@cmb69 cmb69 added the Bug label Sep 15, 2021
Comment on lines 53 to 59
--CLEAN--
<?php
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
$db->exec("drop table bug_78227");
?>
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
--CLEAN--
<?php
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
$db->exec("drop table bug_78227");
?>

This clean section fails on most CI for SQLite3; I assume an in memory DB is used there. Apparently, there is no need for this cleanup, anyway, if the table name is test instead of the custom bug_78227.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks.
I fix it.

@cmb69
Copy link
Member

cmb69 commented Sep 16, 2021

Since this is a bug fix, and I can't see any ABI break, this should probably target an older version; maybe it's too late for PHP-7.4, but PHP-8.0 or at least PHP-8.1 seem to be good candidates.

php_strtolower(statement_val, statement_len);

stmt->select_all = 0;
if (php_memnstr(statement_val, "select", sizeof("select") - 1, end) && php_memnstr(statement_val, "*", sizeof("*") - 1, end)) {
Copy link
Member

Choose a reason for hiding this comment

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

This might not be the best idea. What if we always reset the columns (regardless of the query)? Would that be a real performance issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for your comment.
I'm sorry to reply you so late.
My English is poor but I will try my best to express my thought clearly.

When sql is just like

select * from test where id = ?

It will reset the columns in order to get the latest columns information.

When sql is just like

select foo from test where id = ?

it will not reset columns.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

stmt->columns will not change after the first execute, the key of result set will not change too although we change columns name.

Copy link
Member

Choose a reason for hiding this comment

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

I'm sorry to reply you so late.

No problem! And thank you for the PR!

I think I understand the intention of the code, but select foo from test where name = "*" or even update some_table set selected = 42 where name = "*" would also reset the columns, and generally, it might not be problem to always reset the columns for every execution of the prepared statement (unless that would be a performance bottleneck for some drivers). That appears to be cleaner than trying to detect select statements that need 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.

Oh my god, I did not take that into mind.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cmb69 Thanks for your review.
I should fix this from another perspective.

if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
@$db->exec("drop table test");
Copy link
Member

Choose a reason for hiding this comment

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

Why is there a @? Please don't silence mysterious warnings. If your intention was to ignore the error when the table doesn't exist then use the SQL syntax IF EXISTS

Copy link
Member

Choose a reason for hiding this comment

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

IF EXISTS is non-standard to my knowledge, and as such might not be supported by all drivers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for your comment.
This is my mistake, I am so sorry.
My pr is not perfect enough and I will solve it as soon as possible.

Copy link
Member

Choose a reason for hiding this comment

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

Then a try-catch needs to be used here. If @ was intended then a comment should be put explaining which notice/warning we are ignoring here. Exceptions won't be ignored.

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 am not sure IF EXIST was supported by all database.

@kamil-tekiela
Copy link
Member

I don't like this change. This is something that happens extremely rarely. Changing table structure while reading from the table is not something that is usually done. I'd argue that it happens accidentally, rather than on purpose.

If we want to fix this, then the correct way would be to re-read the column metadata whenever execute is called. Don't special case SELECT * as this looks really sketchy.

@NathanFreeman
Copy link
Contributor Author

I don't like this change. This is something that happens extremely rarely. Changing table structure while reading from the table is not something that is usually done. I'd argue that it happens accidentally, rather than on purpose.

If we want to fix this, then the correct way would be to re-read the column metadata whenever execute is called. Don't special case SELECT * as this looks really sketchy.

You are right. I didn't think very thoughtful. But it is so diffuclt to detect table structure changing or SELECT * .

@NathanFreeman NathanFreeman deleted the bug_78227 branch September 17, 2021 10:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants