Добавить в избранное   Сделать стартовой   Главная   E-mail   Форум   Мой блог 
   
Cертификации

Errors

ETL

FAQ (по темам)

GIS

Web

wiki

Администрирование

Безопасность

Книги
Oracle, ...

Новости

ОС

Программирование

Проектирование БД

Производительность

Скачать

Советы

Тестирование

Установка

FAQ - по базам данных
FAQ - по базам данных
Установка СУБД
Oracle
Sybase
MySQL
PostgreSQL
MS SQL Server
Interbase, Firebird
Другие DB
Администрирование
Oracle
MySQL
Sybase
PostgreSQL
MS SQL Server
Interbase, Firebird
IBM DB2
Другие DB
Проектирование БД
Статьи
ETL
Теория БД
ErWin
Designer 2000
PowerDesigner
Хранилища данных
CASE средства
OLAP
Бизнес - анализ (BI)
Производительность
Oracle
MSSQL
Interbase, Firebird
IBM DB2
MySQL
PostgreSQL
SYBASE
Безопасность БД
Oracle
MS SQL Server
Инъекция SQL
Программирование
Transact-SQL
PL/SQL
C++
XML
SQL
PostgreSQL
MDX
Java
VBA Excel
Книги по базам
Oracle
Заказ книг
ОС
Установка и настройка
UBUNTU
ОС
Установка и настройка
UBUNTU
FAQ
FAQ - по базам данных
Главная arrow PostgreSQL arrow Библиотека полезных функций для PostgreSQL

Библиотека полезных функций для PostgreSQL

Печать E-mail

Библиотека полезных функций для PostgreSQL
Библиотека полезных функций для PostgreSQL

Данная статья содержит выборку PL/PgSQL и SQL функций, которые могут быть полезны разработчикам и администраторам PostgreSQL, а также всем желающим познакомиться с основными процедурными языками в СУБД PostgreSQL на работающих примерах. Большая часть этих функций обсуждалась в англоязычных рассылках и иных каналах общения членов сообщества PostgreSQL, некоторые функции написаны мною. Где это возможно, у функций приведены авторы и небольшие комментарии. Сам лист функций время от времени пополняется, так что следите за изменениями, если примеры представляют для вас интерес.

Генерация случайного пароля 

Вариант 1 

-- Author: Magnus Hagander
CREATE FUNCTION generate_random_password() RETURNS text
AS $$
DECLARE
j int4;
result text;
allowed text;
allowed_len int4;
BEGIN
allowed := '23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ&#%@';
allowed_len := length(allowed);
result := '';
WHILE length(result) < 16 LOOP
j := int4(random() * allowed_len);
result := result || substr(allowed, j+1, 1);
END LOOP;
RETURN result;
END;
$$
LANGUAGE plpgsql;

Вариант 2

-- Author: Jeff Ross
CREATE OR REPLACE FUNCTION gen_password() RETURNS text AS $$
DECLARE
password text;
chars text;
BEGIN
password := '';
chars :=
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
FOR i IN 1..8 LOOP
password := password || SUBSTRING(chars,
ceil(random()*LENGTH(chars))::integer, 1);
END LOOP;
return password;
END;
$$
LANGUAGE plpgsql;

Работа с интервалами: сдвиг на N месяцев


Простая функция на языке SQL для добавления или вычитания из даты заданного количества месяцев.
-- Author: Martijn van Oosterhout
CREATE OR REPLACE FUNCTION GOMONTH(DATE, INTEGER, OUT DATE) IMMUTABLE AS
$_$
SELECT ($1 + ($2 * '1 MONTH'::INTERVAL))::DATE;
$_$ LANGUAGE SQL

Найти всех пользователей данной роли


Рекурсивная функция поиска всех ролей, принадлежащих данной роли. То есть, если роль ID1 имеет членов ID2 и ID3, а в роль ID2 входят роли ID4 и ID5, то функция вернет список всех этих ролей.
-- Author: David Fetter
CREATE OR REPLACE FUNCTION get_roles_under(OID)
RETURNS SETOF OID
LANGUAGE sql
AS $$
SELECT
$1
UNION
SELECT
member
FROM
pg_catalog.pg_auth_members
WHERE
roleid = $1
UNION
SELECT
get_roles_under(roleid) AS "roleid"
FROM
pg_catalog.pg_auth_members
WHERE
roleid IN (
SELECT
member
FROM
pg_catalog.pg_auth_members
WHERE
roleid = $1
)
$$;

Kill бакенда и получение имени текущего пользователя


Довольно глупый, но тем не менее reference-пример прекращения работы бакенда и получения имени пользователя, вызывающего функцию:
CREATE FUNCTION kill_process(integer) RETURNS boolean
AS 'SELECT pg_cancel_backend(procpid)
FROM (SELECT procpid FROM pg_stat_activity WHERE procpid=$1 and usename=session_user)
AS kill;'
LANGUAGE SQL SECURITY DEFINER;

Начало и конец недели по ее номеру в году


Работа с функциями, связанными со временем:
-- Author: Andreas Kretschmer
create or replace function get_week(IN jahr int, IN kw int) returns text as $$
declare
datum date;
ret text;
begin
datum = (jahr || '-01-01')::date;

loop
exit when extract(dow from datum) = 4;
datum = datum + '1day'::interval;
end loop;
ret = to_char(datum+(7*(kw-1)-3||'days')::interval,'dd-mm-yyyy') || ' - ' || to_char(datum+(3+7*(kw-1)||'days')::interval,'dd-mm-yyyy');
return ret;
end;
$$ language plpgsql immutable strict;

-- Example:
test=# select get_week(2007,2);
get_week
-------------------------
08-01-2007 - 14-01-2007

Манипуляции с хозяином/пермиссиями таблиц и функций в схеме


Таблицы

Функция для изменения прав доступа к таблицам в заданной схеме по заданной LIKE-маске. Администраторам должно быть удобно на основании этого прототипа также сделать функции revoke_on_tables() и change_owner_of_tables() -- они будут использовать абсолютно такой же цикл, только динамический SQL внутри него будет несколько иной.

-- Author: Ivan Zolotukhin
-- License: BSD
CREATE OR REPLACE FUNCTION grant_on_tables(role_name text, permission text, mask text, schema_name text)
RETURNS integer LANGUAGE plpgsql
AS $$
-- Function that grants given permissions to given role on tables with given LIKE mask within given schema
-- Example:
-- SELECT grant_on_tables('role_developer','SELECT, INSERT, UPDATE, DELETE, RULE, REFERENCE, TRIGGER','%','public');
-- will grant all the maximum permissions on all tables within public schema to role_developer role
DECLARE
obj record;
num integer;
BEGIN
num := 0;
FOR obj IN
SELECT
relname
FROM
pg_class c
JOIN pg_namespace ns ON (c.relnamespace = ns.oid)
WHERE
relkind in ('r','v','S')
AND nspname = schema_name
AND relname LIKE mask
ORDER BY
relname
LOOP
EXECUTE 'GRANT ' || permission || ' ON ' || obj.relname || ' TO ' || role_name;
RAISE NOTICE '%', 'Done: GRANT ' || permission || ' ON ' || obj.relname || ' TO ' || role_name;
num := num + 1;
END LOOP;
RETURN num;
END;
$$;

Функции

Эта функция является вспомогательной и как правило ее не нужно вызывать руками. Она нужна для получения необходимой информации об аргументах функций, так как в PostgreSQL для манипуляций с хозяином или пермиссиями функции требуется указывать fully-qualified имя со списком аргументов.

-- Author: Ivan Zolotukhin
-- License: BSD
CREATE OR REPLACE FUNCTION pg_get_function_args(
IN funcname character varying,
IN funcargs oidvector,
IN schema character varying,
OUT pos integer,
OUT direction character,
OUT argname character varying,
OUT datatype character varying) RETURNS SETOF RECORD
AS $$
-- For a function name and schema, this procedure selects for each argument the following data:
-- - position in the argument list (0 for the return value)
-- - direction 'i', 'o', or 'b'
-- - name (NULL if not defined)
-- - data type
DECLARE
rettype character varying;
argtypes oidvector;
allargtypes oid[];
argmodes "char"[];
argnames text[];
mini integer;
maxi integer;
BEGIN
/* get object ID of function */
SELECT INTO
rettype,
argtypes,
allargtypes,
argmodes,
argnames
CASE
WHEN
pg_proc.proretset
THEN
'setof ' || pg_catalog.format_type(pg_proc.prorettype, NULL)
ELSE
pg_catalog.format_type(pg_proc.prorettype, NULL)
END,
pg_proc.proargtypes,
pg_proc.proallargtypes,
pg_proc.proargmodes,
pg_proc.proargnames
FROM
pg_catalog.pg_proc
JOIN pg_catalog.pg_namespace ON (pg_proc.pronamespace = pg_namespace.oid)
WHERE
pg_proc.proname = funcname
AND pg_proc.proargtypes = funcargs
AND pg_namespace.nspname = schema
AND pg_catalog.pg_function_is_visible(pg_proc.oid);

/* bail out if not found */
IF NOT FOUND THEN
RETURN;
END IF;

/* return a row for the return value */
pos = 0;
direction = 'o'::char;
argname = 'RETURN VALUE';
datatype = rettype;
RETURN NEXT;

/* unfortunately allargtypes is NULL if there are no OUT parameters */
IF allargtypes IS NULL THEN
mini = array_lower(argtypes, 1);
maxi = array_upper(argtypes, 1);
ELSE
mini = array_lower(allargtypes, 1);
maxi = array_upper(allargtypes, 1);
END IF;

IF maxi < mini THEN
RETURN;
END IF;

/* loop all the arguments */
FOR i IN mini .. maxi
LOOP
pos = i - mini + 1;
IF argnames IS NULL THEN
argname = NULL;
ELSE
argname = argnames[i];
END IF;

IF allargtypes IS NULL THEN
direction = 'i'::char;
datatype = pg_catalog.format_type(argtypes[i], NULL);
ELSE
direction = argmodes[i];
datatype = pg_catalog.format_type(allargtypes[i], NULL);
END IF;
RETURN NEXT;
END LOOP;
RETURN;
END;$$
LANGUAGE plpgsql STABLE STRICT SECURITY INVOKER;

А этот пример представляет непосредственный интерес. Функция выдает необходимые пермиссии всем функциям с названиями, удовлетворяющим LIKE-маске в заданной схеме:

-- Author: Ivan Zolotukhin
-- License: BSD
CREATE OR REPLACE FUNCTION grant_on_functions(role_name text, permission text, mask text, schema_name text)
RETURNS integer LANGUAGE plpgsql
AS $$
-- Function that grants given permissions to given role on functions with given LIKE mask within given schema
-- Example:
-- SELECT grant_on_functions('role_developer','EXECUTE','%','public');
-- will grant the execute permission on all functions within public schema to role_developer role
DECLARE
func record;
func_argument record;
argument_list varchar;
num integer;
BEGIN
num := 0;
/* select all function's names in given schema */
FOR func IN
SELECT
proname, proargtypes
FROM
pg_proc AS pro
JOIN pg_namespace AS ns ON pro.pronamespace = ns.oid
WHERE
ns.nspname = schema_name
AND proname LIKE mask
AND pg_catalog.pg_function_is_visible(pro.oid)
ORDER BY
proname
LOOP
argument_list := '(';
-- get input arguments of the function we're granting permissions on
FOR func_argument IN
SELECT datatype FROM pg_get_function_args(func.proname::varchar, func.proargtypes::oidvector, schema_name) WHERE direction = 'i'
LOOP
argument_list := argument_list || func_argument.datatype || ', ';
END LOOP;

SELECT INTO argument_list rtrim(argument_list, ', ');
argument_list := argument_list || ')';

-- grant permissions when we know complete function designation like
-- my_best_function(varchar, text, integer, float)
EXECUTE 'GRANT ' || permission || ' ON FUNCTION ' || schema_name || '.' || func.proname || argument_list || ' TO ' || role_name;
RAISE NOTICE '%', 'Done: GRANT ' || permission || ' ON FUNCTION ' || schema_name || '.' || func.proname || argument_list || ' TO ' || role_name;
num := num + 1;
END LOOP;
RETURN num;

END;
$$;

Как и в случае с таблицами, администратору может быть удобно использовать функцию change_owner_of_functions(), которая практически не будет отличаться от приведенного выше примера.


 
 
« Пред.   След. »
Взаимосвязанные статьи
     

Последние добавленные статьи
Поиск
Ссылки
Главная
Скачать
Курсы
Роль АБД (SYSDBA)
Карта сайта
Автостекла
Контакты
Войти на сайт
Популярные статьи
Online - тесты
1Z0-042
Rambler's Top100 МЕТА - Украина. Рейтинг сайтов хостинг от freehost.com.ua

Все права защищены.SYSDBA 2010 | Если у Вас есть хороший материал пришлите его нам.