Skip to content

ext/pdo_pgsql: Retrieve the memory usage of the query result resource #14260

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

KentarouTakeda
Copy link
Contributor

This implementation is similar to Pull Request #14214.

I have implemented the same functionality in PDOStatement, specifically for PdoPgsql.

By calling:

$statement->getAttribute(PDO::PGSQL_ATTR_RESULT_MEMORY_SIZE);

You can find out the amount of memory used internally by the client library libpq.
This value was not reflected in the memory_get_usage() output, so it was not possible to determine until now.

PDOStatement differs from PgSql\Result in that it may represent a statement that has not yet been executed.
In this case, libpq does not allocate memory either.Therefore, PDO::PGSQL_ATTR_RESULT_MEMORY_SIZE returns null in such cases.

Since this feature did not require an RFC for ext/pgsql, I am wondering if it is also unnecessary for this implementation. Please let me know if an RFC is needed or if there are any internals discussions required.

@KentarouTakeda KentarouTakeda force-pushed the pgsql-pdo_attr_result_memory_size branch from 215ef4a to 0aaeae6 Compare May 17, 2024 14:12
if(stmt->executed) {
ZVAL_LONG(val, PQresultMemorySize(S->result));
} else {
ZVAL_NULL(val);
Copy link
Member

Choose a reason for hiding this comment

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

I do not know if we should emit a PDO exception in this case, @SakiTakamachi what do you think ?

Copy link
Member

Choose a reason for hiding this comment

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

I think we can throw an exception here, because it's obviously wrong to try to get the size of a result when there is no "result" yet.

Copy link
Member

@SakiTakamachi SakiTakamachi May 18, 2024

Choose a reason for hiding this comment

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

@devnexen

Ah but mainly these are used for debugging purposes?

In that case, throwing an exception might make the method difficult to use.

If it's unexecuted, does it make sense to interpret this as 0 memory allocation and return 0 (or null)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IMO, I prefer to throw an exception for incorrect operations.

On the other hand, if you fetchAll() a statement that has not yet been executed, [] is returned. If consistency is our priority, it may be better not to throw exceptions.

In both cases, it doesn't take me much time since I have the modified code at hand as well.

Copy link
Member

Choose a reason for hiding this comment

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

Rather, it seems like the problem is that fetching an unexecuted result doesn't result in an error....

That's a relic of PDO when exceptions didn't exist, and I don't think it should still be that way if don't take BC into account.

I'll wait for David's opinion.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, excuse me. This also has a status....

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 added pdo_pgsql_error_stmt_msg in da6b54b.

If we should not emit exception, I think the current code is the best.

Copy link
Member

@devnexen devnexen May 19, 2024

Choose a reason for hiding this comment

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

You can even be more informative since you have access to the statement's name.
Note that, with the last changes, your new test is skipped due to the new constant now missing.

Copy link
Member

@devnexen devnexen May 19, 2024

Choose a reason for hiding this comment

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

oh I see, it works only if you enable pgsql too (symbol is defined here).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

@SakiTakamachi SakiTakamachi left a comment

Choose a reason for hiding this comment

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

You're probably better off putting the constants in a stub for the subclass.

e.g. (firebird):
https://github.com/php/php-src/blob/master/ext/pdo_firebird/pdo_firebird.stub.php

@KentarouTakeda
Copy link
Contributor Author

I added a stub and generated arginfo in b5769e6 .

Comment on lines +159 to +161
#ifdef HAVE_PG_RESULT_MEMORY_SIZE
REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_RESULT_MEMORY_SIZE", (zend_long)PDO_PGSQL_ATTR_RESULT_MEMORY_SIZE);
#endif
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 not sure if I should write this down.

The purpose of subclasses is to allow driver specific functionality to be provided in the subclasses.

This statement would mean having the same constants in PDO core, which may go against the subclassing philosophy.

Copy link
Member

Choose a reason for hiding this comment

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

However, since PDO::getAttribute is not a subclass-specific method, I'm not sure what to do.

ZVAL_LONG(val, PQresultMemorySize(S->result));
} else {
char *tmp;
spprintf(&tmp, 0, "statement '%s' has not been executed yet", S->stmt_name);
Copy link
Member

@devnexen devnexen May 19, 2024

Choose a reason for hiding this comment

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

if you re allocating on the heap then you need to free it at some point. If you run your own test you ll see.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, you're right...
I fixed: 218ff1e

@devnexen
Copy link
Member

Looks ok to me overall, I do not think it needs to me made more complicated than it is. As for returning null vs 0, I think null sends stronger message that the usage is wrong which will lead the user to investigate further via the errorinfo. 0 would have been enough in case of exception raised. But that s just me, so @SakiTakamachi feel free to review and merge it when you see fit.

Copy link
Member

@SakiTakamachi SakiTakamachi left a comment

Choose a reason for hiding this comment

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

I've thought again about what's been discussed and agree that the current state looks good.

Regarding whether or not to include constants in pdo core, it seems fine to leave it as it is, i.e. "include" it.

LGMT, There's really just one small nits :)

--TEST--
PDO PgSQL PDOStatement::getAttribute(PDO::PGSQL_ATTR_RESULT_MEMORY_SIZE)
--EXTENSIONS--
pdo
Copy link
Member

Choose a reason for hiding this comment

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

This statement is unnecessary because pdo is always loaded when pdo_pgsql is loaded.

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 fixed: 8701022

@KentarouTakeda
Copy link
Contributor Author

Your very thorough reviews and valuable advice are greatly appreciated. Thank you both so much.

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.

3 participants