One solution is to run the query twice, once with just a count(*) and then the actual query, but that'd be very inefficient.
A few experiments later I think I have a solution; a bit inefficient than running the plain query but much better than running the query twice.
with REAL_QUERY as (select relname, oid from pg_class limit 5) -- User should ignore the rest of the query select *, show_rowcounter() as row_count from (select REAL_QUERY.*, increment_rowcounter() as row_number from REAL_QUERY, (select reset_rowcounter()) as _c order by row_number offset 0) as _subq;
Don't get scared by the length of the query above, all one needs to do is put the real query between the first pair of parenthesis after the REAL_QUERY identifier.
The result would be the same as the original query, but with two additional columns: row_number and row_count. row_number numbers each row starting from 1, and row_count shows the total number of rows in the result.
. relname | oid | row_number | row_count ---------------+------+------------+----------- pg_statistic | 2619 | 1 | 5 pg_type | 1247 | 2 | 5 pg_attribute | 1249 | 3 | 5 pg_toast_1262 | 2844 | 4 | 5 pg_toast_2604 | 2830 | 5 | 5 (5 rows)The 'ORDER BY row_number' clause adds the overhead, but it is necessary so that the row_count is calculated before the first row is produced at the top level. I wish I could introduce a MATERIALIZE node in the query plan at will.
If your REAL_QUERY has an ORDER BY or GROUP BY clause then you can remove the ORDER BY row_number clause from the outer query, since Postgres will make sure that show_rowcounter() will not be called before the last call of increment_rowcounter().
The above trick uses the Common-Table-Expression feature (introduced in Postgres version 8.4), because I wanted to make it look like a template where user's real query is visible at the top.
If you are running on an older version you can easily modify it to be a simple query because CTE used above is not recursive.
select *, show_rowcounter() as row_count from (select REAL_QUERY.*, increment_rowcounter() as row_number from (select relname, oid from pg_class limit 5) as REAL_QUERY, (select reset_rowcounter()) as _c order by row_number offset 0) as _subq;Now the guts of the trickery: PL/Perl functions:
-- PL/Perl create or replace function reset_rowcounter() returns int as $p$ $_SHARED{rowcounter} = 0; $p$ language plperl stable; create or replace function increment_rowcounter() returns int as $p$ $_SHARED{rowcounter} = $_SHARED{rowcounter} + 1; return $_SHARED{rowcounter}; $p$ language plperl; create or replace function show_rowcounter() returns int as $p$ return $_SHARED{rowcounter}; $p$ language plperl;BTW, this also shows how one can get Oracle's ROWNUM like feature in Postgres.