How do I get the PostgreSQL query execution time in PHP using the pg_* functions? I've spent hours on this page now, looking through everything: https://www.php.net/manual/en/ref.pgsql.php
I can't figure out how to get the &quot;query execution time&quot; from a pg_query (and related query execution functions).
I'm not talking about measuring the time before and after the query in the PHP code, but to get the actual &quot;query execution time&quot; (in milliseconds or similar) of the query, which could be slightly different from the time before and after the function was called due to various reasons.
I'm 99% sure that both PostgreSQL and all other SQL database softwares send this information back for each query somehow, but how? It has a bunch of &quot;statuses&quot;, but not the time the query took to run from what I can tell.
I'm 99% sure that both PostgreSQL and all other SQL database softwares send this information back for each query somehow, but how?

It doesn't. PHP's pg_query uses the simple query protocol and pg_query_params the extended query protocol, and in both cases what the client gets back for successful queries is essentially a CommandComplete message, where the only metadata available is a command tag saying:

what type of query it was
how many rows where affected by the query.

If there was a server-side execution time, it would be there, and it's not.
From the documentation:

CommandComplete (B)
Byte1('C')
Identifies the message as a command-completed response.
Int32
Length of message contents in bytes, including self.
String
The command tag. This is usually a single word that identifies which SQL command was completed.
For an INSERT command, the tag is INSERT oid rows, where rows is the number of rows inserted. oid used to be the object ID of the
inserted row if rows was 1 and the target table had OIDs, but OIDs
system columns are not supported anymore; therefore oid is always 0.
For a DELETE command, the tag is DELETE rows where rows is the number of rows deleted.
For an UPDATE command, the tag is UPDATE rows where rows is the number of rows updated.
For a SELECT or CREATE TABLE AS command, the tag is SELECT rows where rows is the number of rows retrieved.
or a MOVE command, the tag is MOVE rows where rows is the number of rows the cursor's position has been changed by.
For a FETCH command, the tag is FETCH rows where rows is the number of rows that have been retrieved from the cursor.
For a COPY command, the tag is COPY rows where rows is the number of rows copied. (Note: the row count appears only in PostgreSQL
8.2 and later.)