Подсчет строк во всех схемах (с предоставленным разрешением) во всех таблицах - PullRequest
1 голос
/ 07 марта 2019

Я пытаюсь подсчитать строки во всех таблицах в базе данных. Поскольку ответ, который я хотел бы получить, должен различать разные схемы, я также принимаю во внимание схему, в которой находится конкретная таблица.

Этот ответ был наиболее полезным, но оказалось, что у меня нет прав доступа ко всем схемам в базе данных.

Я знаю, что могу проверить свои привилегии для конкретной таблицы или схемы, выполнив следующий запрос:

select count(*) from (
SELECT grantee, privilege_type 
FROM information_schema.role_table_grants 
WHERE table_name='data' and privilege_type = 'SELECT') as foo

и проверка, равен ли вывод или больше единицы.

Мой код на данный момент выглядит следующим образом:

CREATE or replace function rowcount_all(schema_name text default 'public')
  RETURNS table(table_name_var text, cnt bigint) as
$$
declare
 table_name_var text;
begin
  for table_name_var in SELECT c.relname FROM pg_class c
    JOIN pg_namespace s ON (c.relnamespace=s.oid)
    WHERE c.relkind = 'r' AND s.nspname=schema_name
  loop
    if (
    select count(*) from (
    SELECT grantee, privilege_type 
    FROM information_schema.role_table_grants 
    WHERE table_name=table_name_var and privilege_type = 'SELECT') as foo
  ) >= 1 then 
    RETURN QUERY EXECUTE format('select cast(%L as text),count(*) from %I.%I',
       table_name_var, schema_name, table_name_var);
    end if;
  END loop;
end
$$ language plpgsql;

при выполнении следующего запроса

WITH rc(schema_name,tbl) AS (
  select s.n,rowcount_all(s.n) from (values ('schema1'),
    ('schema2'), ('schema3'), ('schema4')) as s(n)
)
SELECT schema_name,(tbl).* FROM rc;

Я получаю сообщение об ошибке ERROR: permission denied for relation table1, где table1 в схеме, к которой у меня нет доступа. Я предполагаю, что моя логика в операторе IF почему-то не отфильтровывает таблицы, к которым у меня нет доступа.

1 Ответ

1 голос
/ 07 марта 2019

information_schema, являющееся стандартным представлением метаданных базы данных SQL, полезно, если вы пытаетесь создать что-то переносимое, но часто немного громоздко, если вы просто пытаетесь администрировать Сервер Postgres.

Самый простой способ проверить привилегии - это использовать функции проверки привилегий . Я считаю, что это вернет только таблицы, которые вы можете запросить:

select oid::regclass::text
from pg_class
where relkind = 'r'
  and relnamespace = schema_name::regnamespace
  and has_schema_privilege(relnamespace, 'USAGE')
  and has_any_column_privilege(oid, 'SELECT')

Обратите внимание, что у вас один из редких случаев, когда has_any_column_privilege() полезен (по сравнению с более очевидным has_table_privilege()), поскольку вам не нужны полные привилегии для таблицы для select count(*), просто доступ к одному из столбцы (но не важно какие).

Также обратите внимание, что oid::regclass::text вернет имя таблицы, которая уже заключена в кавычки и дополнена схемой (при необходимости), поэтому при вызове format() можно использовать простой %s вместо %I.%I.

Если вы можете обойтись с приблизительным и немного устаревшим количеством записей, вы можете полностью обойти проверки привилегий (и сэкономить много проверок таблиц), запрашивая статистику с последнего запуска VACUUM :

select
  oid::regclass::text,
  reltuples
from pg_class
where relkind = 'r'
  and relnamespace = schema_name::regnamespace
...